1 puan yazan GN⁺ 2024-07-06 | 1 yorum | WhatsApp'ta paylaş

Kurucum yok ve başlatılmam gerekiyor

  • Giriş

    • C++ öğrenmeye ilk başladığımda, derleyicinin varsayılan kurucuyu sağladığı durumları öğrendim.
    • Belirli durumlarda nesnenin başlatılmadan kalabilmesi riskini düşünmeye başladım.
  • Varsayılan başlatma ve değer başlatma

    • T t; varsayılan başlatma yapar.
      • T bir sınıf türüyse ve varsayılan kurucusu varsa bu çalıştırılır.
      • T bir dizi türüyse her öğe varsayılan olarak başlatılır.
      • Aksi halde hiçbir şey yapılmaz.
    • T t{}; değer başlatma yapar.
      • T bir sınıf türüyse ve varsayılan kurucusu yoksa ya da kullanıcı tarafından sağlanmış veya silinmiş bir varsayılan kurucusu varsa, varsayılan başlatma yapılır.
      • Aksi halde önce 0 ile başlatılır, ardından varsayılan başlatma yapılır.
      • T bir dizi türüyse her öğe değer başlatılır.
      • Aksi halde 0 ile başlatılır.
  • Varsayılan kurucu

    • Varsayılan kurucu bildirilmezse derleyici örtük olarak bir varsayılan kurucu bildirir.
    • Örtük olarak bildirilen varsayılan kurucu, boş bir gövdeye ve boş bir üye başlatma listesine sahiptir.
    • Örnek:
      struct T {
        int x;
        T() = default;
      };
      T t{};
      std::cout << t.x << std::endl; // çıktı 0
      
  • Örtük olarak tanımlanan varsayılan kurucu

    • Varsayılan kurucu örtük olarak bildirilmişse veya açıkça varsayılan olarak bildirilmişse, derleyici örtük olarak tanımlanmış bir varsayılan kurucu sağlar.
    • Örnek:
      struct T {
        T();
      };
      T::T() = default;
      T t{};
      std::cout << t.x << std::endl; // çıktı çöp değer
      
  • Varsayılan kurucunun sağlanamadığı durumlar

    • T statik olmayan bir referans üyeye sahipse
    • T, varsayılan olarak oluşturulamayan veya yok edilemeyen statik olmayan bir üyeye ya da soyut olmayan bir taban sınıfa sahipse
    • T, varsayılan üye başlatıcısı olmayan const bir statik olmayan üyeye sahipse
  • Doğru başlatma

    • T t{}; liste başlatma yapar.
    • Liste başlatma, doğrudan liste başlatma ve kopya liste başlatma olarak ayrılır.
    • Örnek:
      struct S {
        int a;
        float b;
        char c;
      };
      S s{3, 4.0f, 'S'}; // kurucu çağrısı yok
      
  • Liste başlatma ve aggregate başlatma

    • Aggregate başlatma, liste başlatmanın özel bir biçimidir; sınıfın veya dizinin her öğesi, başlatma listesindeki karşılık gelen öğeyle kopya başlatılır.
    • Örnek:
      struct A {
        const int x;
      };
      A a{}; // a.x 0 ile başlatılır
      
  • Parantez kullanarak başlatma

    • Parantezle başlatma, doğrudan liste dışı başlatma yapar.
    • Örnek:
      struct T {
        const int& r;
      };
      T t(42); // t.r, 42'yi gösteren bir referanstır
      
  • Özet

    • Başlatma kuralları karmaşıktır, ancak kurucuyu doğrudan yazarsanız çoğu sorundan kaçınabilirsiniz.
    • Bunu derleyiciye bırakmak yerine kurucuyu kendiniz yazmanız daha iyidir.

GN⁺ görüşü

  • Bu yazı, C++ başlatma kurallarının karmaşıklığını iyi açıklıyor.
  • C++'ta başlatma kurallarını anlamak önemlidir; çünkü bu, kodun kararlılığı ve performansı üzerinde büyük etkiye sahiptir.
  • Başlatma sorunlarını önlemenin en iyi yolu kurucuyu doğrudan yazmaktır.
  • Benzer işlevlere sahip başka bir dil olarak Rust vardır; Rust'ta başlatma kuralları daha nettir.
  • Yeni bir teknolojiyi benimserken, başlatma kuralları gibi ayrıntıları iyi anlamak ve doğru kullanmak önemlidir.

1 yorum

 
GN⁺ 2024-07-06
Hacker News yorumu
  • t için başlatma sonucu 0 olacaktır

    • Bunun nedeni t'nin değer başlatmasıyla başlatılması ve T'nin kullanıcı tanımlı varsayılan yapıcısı olmadığı için nesnenin önce 0 ile başlatılıp ardından varsayılan yapıcının çağrılmasıdır
  • Varsayılan yapıcı üyeleri varsayılan olarak başlatır; bu, değer başlatmasından farklıdır

  • GCC de buna katılıyor gibi görünüyor

  • Yazarın aslında x'i değer başlatmasıyla başlattığını gözden kaçırdığı anlaşılıyor

    • Sonuç da bu yüzden beklenenden farklı çıkıyor
  • Kuralların ayrıntıları karmaşık ve yer yer mantıksız

    • Ancak çoğu durumda beklenen sonucu almak mümkün
  • Varsayılan başlatmayı açıkça ifade edebilmek büyük bir iyileştirme olurdu

    • Değer başlatması yaygın olduğu için, varsayılan başlatma isteniyorsa yorum yazmak gerekiyor
    • std::array<int, 100> = void; gibi bir sözdizimi daha iyi olurdu
  • Liste başlatma ile toplu başlatma arasındaki bağ, liste başlatmanın aggregate üzerinde uygulanması durumunda toplu başlatmanın yapılmasıdır

    • Ancak listede yalnızca tek bir argüman varsa doğrudan başlatma yapılır
  • Tek öğe durumu, iki veya daha fazla öğe durumundan farklı çalışır

    • Bu da, parametre paketiyle struct oluşturmanın giderek daha kolaylaştığı bir dilde ortaya çıkıyor
  • Kendi yapıcınızı yazabilir ve tek bir öğe verilmiş tuple ya da array'i başlatabilirsiniz

    • Ancak özel durumlarda yanlış yapıcı çağrılabilir
  • C++11 başlatma listeleri ilk çıktığında bunu fark edip bunun delilik olduğunu düşünmüştüm

  • "I Have No Mouth, and I Must Scream" (1967) anılıyor

  • T::T() = default; sözdizimi kullanılıyor

  • Çıktının 0 olmasını beklersiniz ama gerçekte çöp bir değer çıkacaktır

    • Bazı şeyler kusursuz olamıyor
  • Kütüphane tüketicisinin kütüphanenin davranışını değiştirebilmesine izin veriyor

  • Daha fazla C++ karmaşıklığı istiyorsanız C++ FQA öneriliyor

    • Aradan 15 yıl geçmiş olsa da C++ eski özellikleri ya da davranışları neredeyse hiç kaldırmadığı için hâlâ geçerli
  • Blog teması DEC döneminin bilgisayarlarından ilham alıyor ama temiz ve minimalist

    • Ferah hissettiriyor
  • Bunu okuyunca insanın başı dönüyor

    • Java yapıcılarını ve nesne başlatmayı anlamaya çalıştığım günleri hatırlattı
  • Go ve Rust'ta özel yapıcılar olmadığı için birçok şey daha basit

    • Yapıcı kullanmamaya alıştıktan sonra onları özleyen oldu mu diye merak ediyorum
  • Tüm örtük davranışları gösteren bir C++ aracı olup olmadığını merak ediyorum

    • Örneğin eklenen tüm yapıcılar, örtük kopya yapıcısı vb.
  • Sınıf hakkında yanlış bilgi veriliyor

    • Bir yapıcı bildirilmişse varsayılan yapıcı sağlanmaz ve varsayılan başlatma derleyici tanısıyla başarısız olur
  • T t; ifadesinin "hiçbir şey yapmaz" olduğu iddiası yanlış

    • Örnek kodda T t; başarısız oluyor
  • Blog başlığında bir DEC ön paneli var