ProgramlamaC++ geliştiricisi

C++'da nesnelerin doğrudan ve dolaylı olarak başlatılması arasındaki fark nedir ve yerleşik ve kullanıcı tanımlı türlerle çalışırken ortaya çıkabilecek sonuçlar nelerdir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

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:

  1. Yerleşik türler için davranış aynıdır. Sınıflar için — çağrılan yapılandırıcıların kümesi farklı olabilir veya hatta başlatma yasaklanabilir.
  2. Üye başlatma listesi, derleyici gereksinimleri nedeniyle her başlatma yönteminde her zaman eşdeğer değildir.
  3. Copy elision (gereksiz kopyalamaların ortadan kaldırılması için derleyici optimizasyonu) farkı genellikle ortadan kaldırır (ama her zaman değil, özellikle C++17'den önce).

Ö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

Tuzaklı Soru

"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.

Konuyla ilgili ince detaylardan kaynaklanan gerçek hataların örnekleri


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.