In C++ si distinguono l'inizializzazione diretta (direct) e l'inizializzazione indiretta (copy) degli oggetti:
Inizializzazione diretta:
MyClass obj(arg1, arg2); int x(5);
Per le classi viene chiamato direttamente il costruttore appropriato.
Inizializzazione indiretta:
MyClass obj = MyClass(arg1, arg2); int x = 5;
Questo crea un oggetto temporaneo, quindi lo copia (o lo sposta) (usa il costruttore di copia/spostamento).
Differenze:
Esempio:
struct NonCopyable { NonCopyable(int) {} NonCopyable(const NonCopyable&) = delete; }; NonCopyable a(5); // OK: diretto NonCopyable b = NonCopyable(5); // OK con ottimizzazione, errore prima di C++17 senza di essa NonCopyable c = 5; // Errore: non c'è costruttore di copia
"La copy-initialization può causare più chiamate ai costruttori rispetto alla direct-initialization, se si utilizza C++11 e un compilatore ottimizzante?"
Risposta: Teoricamente — sì. Senza copy elision la copy-initialization crea un oggetto temporaneo, quindi chiama il costruttore di copia o spostamento. La direct-initialization chiama sempre solo il costruttore principale. Tuttavia, i moderni compilatori con ottimizzazione attivata (C++17 e successivi) eliminano questa differenza grazie alla guaranteed copy elision.
Storia
In un progetto finanziario è stata utilizzata la copy-initialization con un oggetto temporaneo, mentre il tipo richiesto non aveva un costruttore di copia. L'applicazione non si compilava su compilatori più vecchi (prima di C++17), anche se la direct-init funzionava.
Storia
In un'utilità di serializzazione dei dati i programmatori pensavano che direct-init e copy-init fossero equivalenti. Di conseguenza si verificavano copie superflue di grandi strutture e cali di prestazioni.
Storia
Durante l'inizializzazione di array globali di oggetti utente è stata utilizzata l'inizializzazione indiretta. Gli errori si manifestavano solo su una piattaforma, dove la copy elision non avveniva, e si verificavano chiamate implicite di costruttori superflui a causa delle peculiarità dell'ABI.