In C++ unterscheidet man zwischen direkter (direct) und indirekter (copy) Initialisierung von Objekten:
Direkte Initialisierung:
MyClass obj(arg1, arg2); int x(5);
Bei Klassen wird der entsprechende Konstruktor direkt aufgerufen.
Indirekte Initialisierung:
MyClass obj = MyClass(arg1, arg2); int x = 5;
Dies erstellt ein temporäres Objekt und kopiert (oder verschiebt) es dann (verwendet den Kopier- oder Verschiebekonstruktor).
Unterschiede:
Beispiel:
struct NonCopyable { NonCopyable(int) {} NonCopyable(const NonCopyable&) = delete; }; NonCopyable a(5); // OK: direkt NonCopyable b = NonCopyable(5); // OK mit Optimierung, Fehler vor C++17 ohne NonCopyable c = 5; // Fehler: kein Kopierkonstruktor vorhanden
"Kann die copy-initialization mehr Konstruktoraufrufe verursachen als die direct-initialization, wenn C++11 verwendet wird und ein optimierender Compiler aktiviert ist?"
Antwort: Theoretisch – ja. Ohne Copy Elision erstellt die copy-initialization ein temporäres Objekt und ruft dann den Kopier- oder Verschiebekonstruktor auf. Die direct-initialization ruft immer nur den Hauptkonstruktor auf. Moderne Compiler mit aktivierter Optimierung (C++17 und höher) beseitigen jedoch diesen Unterschied durch garantierte Copy Elision.
Geschichte
In einem Finanzprojekt wurde die copy-initialization mit einem temporären Objekt verwendet, während der benötigte Typ keinen Kopierkonstruktor hatte. Die Anwendung ließ sich auf älteren Compilern (vor C++17) nicht kompilieren, obwohl die direct-init funktionierte.
Geschichte
In einem Datenserialize-Utility gingen Programmierer davon aus, dass direct-init und copy-init äquivalent sind. Infolgedessen traten unnötige Kopien großer Strukturen auf und es kam zu Leistungsproblemen.
Geschichte
Bei der Initialisierung globaler Arrays benutzerdefinierter Objekte wurde indirekte Initialisierung verwendet. Fehler traten nur auf einer Plattform auf, auf der keine Copy Elision stattfand, und es gab implizite Aufrufe zusätzlicher Konstruktoren aufgrund von ABI-Eigenheiten.