Unterschied zwischen Typendeklaration = und ()
-
Hallo,
ich benutzt C++ mit dem Gnu Compiler und Code::Blocks.
Was ist der Unterschied bei den Typendeklarationen mit Wertzuweisung zwischen '=' und den Klammern?
int zahl1 = 123; // und
int zahl2 (123);oder
string str1 = "abc"; // und
string str2 ("abc");Das Resultat bei Ausgabe mit cout ist ja dasgleiche.
Danke.
-
Nicht für jeden Typen macht es einen Unterschied, aber für einige. Die erste Syntax mit dem Gleichzeichen nennt sich Kopierinitialisierung
T x = soundso; // copy initializationDie zweite Syntax mit den Klammern nennt sich Direktinitialisierung
T x (soundso); // direct initializationDie Kopierinitialisierung ist auch die, die bei der Parameterübergabe oder Rückgabe eines Funktionswertes stattfindet.
Schau mal, was es für einen Unterschied bei expliziten Konstruktoren macht:
vector<double> x = 2; // kompiliert nicht! Keine implizite Konvertierung vector<double> y (2); // OK, y.size()==2intist nicht implizit zuvector<double>konvertierbar. Also funktioniert das hier mit der Kopierinitialisierung nicht.vector<double>besitzt aber einen mitexplicitmarkierten Konstruktor, der eine Ganzzahl entgegen nimmt, die die Größe des zu erstellenden Vektors steuert. Die Klammersyntax ist quasi der direkte Aufruf dieses Konstruktors. Konstruktoren, die mit einem Parameter aufrufbar sind, aber nichtexplicitsind, nennt man auch Konvertierungskonstruktor (Kopier/Move-Konstruktoren mal ausgenommen). So einen Konvertierungskonstruktor bietet std::vector<> nur für initialiter_list<> an, so dass du sowohlvector<double> v = {3.142, 2.718, 1.618}; // copy list initializationals auch
vector<double> w {3.142, 2.718, 1.618}; // direct list initializationschreiben kannst (in C++2011).
Der wesentliche Unterschied hier ist, dass für Kopierinitialisierung nur implizite und keine expliziten Konstruktoren in Frage kommen und dass der Typ kopierbar oder "movebar" sein muss (auch wenn die Verwendung eines solchen Konstruktors bei der Initialisierung wegoptimiert werden könnte).
-
Hallo und danke mal für die Antwort.
So wie ich es verstanden habe, gibt es bei expliziten Konstruktoren keine Möglichkeit der Kopierinitialisation.
Bei einfachen Typen, wie INT, CHAR, STRING ist beides möglich.
So scheint die Direktinitialisierung bspw. 'INT x (12345);' allgemein der Kopierinitialisierung vorzuziehen zu sein.
Gibt es bei der Direktinitialisierung einen Nachteil (Codelänge, Laufzeit) ?
Gruß
-
minotaurus schrieb:
Bei einfachen Typen, wie INT, CHAR, STRING ist beides möglich.
Ich würde nicht sagen, dass std::string ein "einfacher" ist. Kommt aber drauf an, was du damit meinst.

std::string bietet zumindest einen Konvertierungskonstruktor an, der einen
const char*-Wert entgegen nimmt. Deswegen sind beide Initialisierungen möglich (copy und direct).minotaurus schrieb:
Gibt es bei der Direktinitialisierung einen Nachteil (Codelänge, Laufzeit)?
Nö. Aber auch keinen wirklichen Vorteil, falls beide Initialisierungen zulässig sind.
-
Ok - danke !
-
minotaurus schrieb:
So scheint die Direktinitialisierung bspw. 'INT x (12345);' allgemein der Kopierinitialisierung vorzuziehen zu sein.
Wieso das denn?! Ich sehe nicht, wie du darauf gekommen bist.
-
minotaurus schrieb:
Gibt es bei der Direktinitialisierung einen Nachteil (Codelänge, Laufzeit) ?
Codelängen und Laufzeitmäßig nicht. Rein theoretisch muss der Copy-Ctor für Copy-Initialization vorhanden zu erreichbar sein, damit das erlaubt ist. De facto wird er dann aber nicht aufgerufen, weil wegoptimiert.
-
Also wenn ich das jetzt richtig verstanden hab, wird hier
struct Zahl { int wert; Zahl(int x) : wert(x) {} }; //... Zahl z = 3;Zahl z = 3 zu Zahl z(Zahl(3)) und dann wird implizit der jeweilige (automatisch generierte) Kopierkonstruktor aufgerufen?
EDIT: Und explicit verhindert genau das eben, so als würde der Kopierkonstruktor private werden? Und was soll das bringen?
-
@minotaurus
Typendeklarationen ist in dem Zusammenhang Quatsch. Das wovon du redest ist eine Variablendefinition.@Incocnito
Was soll was bringen?
Und nö, mit "so als würde der Kopierkonstruktor private werden" kann man das nicht beschreiben.
explicitverbietet dass ein Konstruktor implizit aufgerufen wird. Also an Stellen wo der Compiler ein A hat und Funktionen die bloss ein B entgegennehmen darf er den Konstruktorexplicit B(A const&)nicht verwenden um die Konvertierung durchzuführen.
-
Incocnito schrieb:
Also wenn ich das jetzt richtig verstanden hab, wird hier
struct Zahl { int wert; Zahl(int x) : wert(x) {} }; //... Zahl z = 3;Zahl z = 3 zu Zahl z(Zahl(3))
und dann wird implizit der jeweilige (automatisch generierte) Kopierkonstruktor aufgerufen?
Da bin ich mir nicht sicher aber ich denke dass da einfach der Konvertierungskonstruktor aufgerufen wird.
-
Hacker schrieb:
Incocnito schrieb:
und dann wird implizit der jeweilige (automatisch generierte) Kopierkonstruktor aufgerufen?
Da bin ich mir nicht sicher aber ich denke dass da einfach der Konvertierungskonstruktor aufgerufen wird.
Wenn ich das richtig im Kopf hab ist beides ganz knapp daneben, die Wahrheit liegt dazwischen:
- Der automatisch generierte Copy-Ctor kann hier aufgerufen werden. er sollte aber auf jeden Fall erreichbar sein (d.h. nicht private/protected)
- Der Copy-Ctor muss nicht aufgerufen werden. IIRC sagt der Standard explizit, dass er zwar existieren muss, aber wegoptimiert werden darf.