C++'da nesnelerin doğrudan (direct) ve dolaylı (copy) başlatılması arasında ayrım yapılır:
Doğrudan başlatma:
MyClass obj(arg1, arg2); int x(5);
Sınıflar için uygun yapılandırıcıyı doğrudan çağırır.
Dolaylı başlatma:
MyClass obj = MyClass(arg1, arg2); int x = 5;
Bu, geçici bir nesne oluşturur ve ardından onu kopyalar (veya taşır) (kopyalanan/taşınan yapılandırıcıyı kullanır).
Farklılıklar:
Örnek:
struct NonCopyable { NonCopyable(int) {} NonCopyable(const NonCopyable&) = delete; }; NonCopyable a(5); // TAMAM: doğrudan NonCopyable b = NonCopyable(5); // OPTİMİZASYON ile TAMAM, C++17 öncesi hata NonCopyable c = 5; // HATA: kopyalama yapılandırıcısı yok
"Copy-initialization, C++11 kullanıldığında ve optimizasyon yapan bir derleyici ile, direct-initialization'dan daha fazla yapılandırıcı çağrısı yapabilir mi?"
Cevap: Teorik olarak — evet. Copy elision olmadan copy-initialization geçici bir nesne oluşturur, ardından kopyalama veya taşıma yapılandırıcısını çağırır. Direct-initialization her zaman yalnızca temel yapılandırıcıyı çağırır. Ancak modern derleyiciler, optimize edilmiş C++17 ve üstü ile bu farklılığı guaranteed copy elision ile ortadan kaldırır.
Hikaye
Finans projesinde, dolaylı başlatma ile geçici bir nesne kullanıldı ve gerekli türde kopyalama yapılandırıcısı yoktu. Uygulama eski derleyicilerde (C++17 öncesi) derlenmedi, oysa doğrudan başlatma çalışıyordu.
Hikaye
Veri serileştirme aracında, programcılar doğrudan başlatma ve dolaylı başlatmanın eşdeğer olduğunu düşündüler. Sonuç olarak, büyük yapılar üzerinde gereksiz kopyalamalar meydana geldi ve performans kayıpları oluştu.
Hikaye
Kullanıcı nesnelerinin küresel dizilerini başlatırken dolaylı başlatma kullanıldı. Hatalar yalnızca kopyalama elision'ın olmadığı bir platformda ortaya çıktı ve ABI'nin özellikleri nedeniyle gereksiz yapılandırıcı çağrıları oluştu.