Ich beobachtete die folgenden Vektorkonstruktoren in der Standard-C ++ - Bibliothek
%Vor% Gibt es einen Grund, warum der zweite Konstruktor nicht als explicit
markiert ist? Das kompiliert und macht mich schlecht fühlen
Wenn ich das "foo"
weglasse, kompiliert es nicht, und das erwarte ich, wenn ich einen Paar (zusammengesetzten) Wert eines int und eines Strings an eine Funktion übergebe, die einen Vektor von Strings haben will.
Ich frage mich, ob es in erster Linie legitim ist zu erwarten, dass { ... }
immer eine Liste von Containerelementen darstellt, wenn ein temporäres erstellt wird. Dies scheint deine Annahme zu sein. IMO der Einargumentkonstruktor muss als explicit
deklariert werden, um unerwünschte Konvertierungssequenzen oder bedeutungslose Zuweisungen wie:
Andererseits kann dieser Konstruktor für die Zwei-Argument-Version, wenn ein Temporär erstellt wird, mit der Verwendung geschweifter Klammern aufgerufen werden, was dem Programmierer bekannt ist was er da reinlegt. Zum Beispiel ist es für mich ziemlich klar, dass 10
und "hello"
nicht dazu gedacht sind, eine Liste von Containerelementen darzustellen, weil 10
keine Zeichenkette ist.
Wenn ich wirklich einen Vektor von 10 Elementen übergeben wollte, die auf "hello"
initialisiert wurden, würde es mich stören, wenn ich f(vector(10, "hello"))
schreiben müsste anstatt nur f({10, "hello"})
.
Also, um es zusammenzufassen: Während der Konstruktor mit einem Argument als explicit
deklariert werden muss, glaube ich, dass dies für den Zwei-Argument-Wert nicht obligatorisch ist, weil nicht alles, was in einem Paar geschweifter Klammern ist, sein sollte interpretiert als eine Liste von Containerelementen.
Wenn ich das "foo" weglasse, kompiliert es nicht und das ist, was ich erwarte wenn ich einen Paar (zusammengesetzten) Wert eines int und eines Strings an eine Funktion übergebe, die will ein Vektor von Strings.
Nein, Sie übergeben kein Paar int und eine Zeichenfolge, sondern Sie erstellen einen Vektor der Größe 10 mit dem Inhalt von Strings wie "foo". Da ist nichts falsch daran! Ich kann eine Situation darstellen, in der es nützlich sein kann, einen Vektor zu erstellen, der die gleichen Strings von Anfang an enthält.
das erwarte ich, wenn ich einen Paar (zusammengesetzten) Wert eines int und eines Strings an eine Funktion übergebe, die einen Vektor von Strings haben will.
Nun, da ist dein Problem.
{...}
ist kein "zusammengesetzter Wert". Es ist keine Liste. Es heißt "initialisiere ein Objekt mit diesen Werten". Wenn das fragliche Objekt ein Aggregat ist, verwendet es die Aggregat-Initialisierung. Wenn es sich bei dem Objekt um einen nicht aggregierten Typ handelt, wird ein aufzurufender Konstruktor ausgewählt, basierend auf den übereinstimmenden Konstruktoren des Typs und den verschiedenen Regeln für stacked-init-Listen in C ++ 11.
Sie sollten nicht an {10, "foo"}
als Liste von zwei Werten denken. Es ist ein Initialisierer, der zwei Werte enthält. Es könnte mit std::pair<int, const char *>
und so weiter verwendet werden.
Der Grund, warum der Konstruktor von std::vector
nicht explizit ist, ist genau erlaubt dieses Konstrukt. Der Konstruktor mit einem Argument ist explizit, da andernfalls implizite Konvertierungsregeln dies zulassen würden:
Oder, was noch wichtiger ist:
%Vor% Wir möchten nicht, dass ganze Zahlen implizit in std::vector
s umgewandelt werden können. Wenn Sie jedoch einen Initialisierer verwenden, ist es sinnvoller, einen größeren Bereich von "impliziten" Konvertierungen zuzulassen, da Sie die {}
-Syntax dort sehen können.
Bei dem Fall mit einem Argument ist nicht klar, was der Benutzer meint. Mit der Syntax {} ist klar, was der Benutzer meint: um das Objekt zu initialisieren.
%Vor%Tags und Links c++ c++11 constructor explicit equivalence