In C++ worden directe (direct) en indirecte (copy) initialisatie van objecten onderscheiden:
Directe initialisatie:
MyClass obj(arg1, arg2); int x(5);
Voor klassen wordt de juiste constructor direct aangeroepen.
Indirecte initialisatie:
MyClass obj = MyClass(arg1, arg2); int x = 5;
Dit creëert een tijdelijke object en kopieert (of verplaatst) het vervolgens (maakt gebruik van de kopieer-/verhuisconstructor).
Verschillen:
Voorbeeld:
struct NonCopyable { NonCopyable(int) {} NonCopyable(const NonCopyable&) = delete; }; NonCopyable a(5); // OK: directe NonCopyable b = NonCopyable(5); // OK met optimalisatie, fout tot C++17 zonder NonCopyable c = 5; // Fout: geen kopieerconstructor
"Kan copy-initialization meer aanroepen van constructors veroorzaken dan direct-initialization, als C++11 wordt gebruikt en een optimaliserende compiler is ingeschakeld?"
Antwoord: Theoretisch — ja. Zonder copy elision creëert copy-initialization een tijdelijk object en roept vervolgens de kopieer- of verhuisconstructor aan. Direct-initialization roept altijd alleen de hoofdconstructor aan. Moderne compilers met inschakeling van optimalisatie (C++17 en hoger) elimineren dit verschil dankzij guaranteed copy elision.
Verhaal
In een financieel project werd copy-initialization met een tijdelijk object gebruikt, terwijl het benodigde type geen kopieerconstructor had. De applicatie compileerde niet op oude compilers (voor C++17), hoewel direct-init werkte.
Verhaal
In de gegevensserialisatie-tool dachten programmeurs dat direct-init en copy-init gelijkwaardig waren. Dit leidde tot overbodige kopieën van grote structuren en prestatieproblemen.
Verhaal
Bij het initialiseren van globale arrays van gebruikersobjecten werd indirecte initialisatie gebruikt. Fouten manifesteerden zich alleen op één platform, waar copy elision niet plaatsvond, en er ontstonden impliciete aanroepen van overbodige constructors door de kenmerken van de ABI.