Kurucusuz başlatma gerekliliği
(consteval.ca)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.Tbir sınıf türüyse ve varsayılan kurucusu varsa bu çalıştırılır.Tbir 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.Tbir 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.
Tbir 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
Tstatik olmayan bir referans üyeye sahipseT, varsayılan olarak oluşturulamayan veya yok edilemeyen statik olmayan bir üyeye ya da soyut olmayan bir taban sınıfa sahipseT, varsayılan üye başlatıcısı olmayanconstbir 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
Hacker News yorumu
tiçin başlatma sonucu 0 olacaktırt'nin değer başlatmasıyla başlatılması veT'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ırVarsayı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ıyorKuralların ayrıntıları karmaşık ve yer yer mantıksız
Varsayılan başlatmayı açıkça ifade edebilmek büyük bir iyileştirme olurdu
std::array<int, 100> = void;gibi bir sözdizimi daha iyi olurduListe 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
Tek öğe durumu, iki veya daha fazla öğe durumundan farklı çalışır
Kendi yapıcınızı yazabilir ve tek bir öğe verilmiş tuple ya da array'i başlatabilirsiniz
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
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
Blog teması DEC döneminin bilgisayarlarından ilham alıyor ama temiz ve minimalist
Bunu okuyunca insanın başı dönüyor
Go ve Rust'ta özel yapıcılar olmadığı için birçok şey daha basit
Tüm örtük davranışları gösteren bir C++ aracı olup olmadığını merak ediyorum
Sınıf hakkında yanlış bilgi veriliyor
T t;ifadesinin "hiçbir şey yapmaz" olduğu iddiası yanlışT t;başarısız oluyorBlog başlığında bir DEC ön paneli var