Aşağıdaki ifadeler C ++ ile ne anlama geliyor:
sıfır başlatma,
varsayılan başlatma ve
değer başlatma
Bir C ++ geliştiricisi onlar hakkında ne bilmeli?
Aşağıdaki ifadeler C ++ ile ne anlama geliyor:
sıfır başlatma,
varsayılan başlatma ve
değer başlatma
Bir C ++ geliştiricisi onlar hakkında ne bilmeli?
Yanıtlar:
Gerçekleşmesi gereken bir şey, 'değer başlatma' C ++ 2003 standardında yeni olmasıdır - orijinal 1998 standardında mevcut değildir (bir açıklamadan daha fazla olan tek fark olabilir). Doğrudan standarttan tanımlar için Kirill V. Lyadvinsky'nin cevabına bakınız .
Bu operator new
başlatma türünün farklı davranışları ve ne zaman devreye girdikleri (ve c ++ 98'den C ++ 03'e farklılık gösterdiklerinde) hakkındaki ayrıntılar için önceki davranışına bakın:
Cevabın ana noktası:
Bazen yeni işleç tarafından döndürülen bellek başlatılır ve bazen yeni sürdüğünüz türün POD olmasına veya POD üyeleri içeren ve derleyici tarafından oluşturulan varsayılan kurucu kullanıp kullanmadığına bağlı olmaz. .
- C ++ 1998'de 2 başlatma türü vardır: sıfır ve varsayılan
- C ++ 2003'te 3. tür bir başlatma, değer başlatma eklendi.
En azını söylemek gerekirse, oldukça karmaşıktır ve farklı yöntemler devreye girdiğinde süptildir.
Kesinlikle bilinmesi gereken bir şey, MSVC'nin VS 2008'de (VC 9 veya cl.exe sürüm 15.x) bile C ++ 98 kurallarına uymasıdır.
Aşağıdaki snippet, MSVC ve Digital Mars'ın C ++ 98 kurallarına, GCC 3.4.5 ve Comeau'nun C ++ 03 kurallarına uyduğunu göstermektedir:
#include <cstdio>
#include <cstring>
#include <new>
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m
int main()
{
char buf[sizeof(B)];
std::memset( buf, 0x5a, sizeof( buf));
// use placement new on the memset'ed buffer to make sure
// if we see a zero result it's due to an explicit
// value initialization
B* pB = new(buf) B(); //C++98 rules - pB->m is uninitialized
//C++03 rules - pB->m is set to 0
std::printf( "m is %d\n", pB->m);
return 0;
}
int
değil m()
, üçüncü satırdaki değer m'yi başlatır. Olarak değiştirirseniz int m;
önemlidir B m;
. :)
A
ve C
bu örnekte kullanılmıyor (diğer bağlantılı cevaptan taşınıyor). C ++ 98 ve C ++ 03 nasıl A
ve nasıl C
yapılandırıldıklarını açıklarken farklı terminoloji kullansalar da sonuç her iki standartta da aynıdır. Yalnızca struct B
farklı davranışlarla sonuçlanır.
struct C { C() : m() {}; ~C(); B m; };
, o zaman m.m
0 olacaktır. Ancak m
C ++ 03'ün söylediği gibi varsayılan başlangıç yaparsa, m.m
C ++ 98'deki gibi başlatılmaz.
C ++ 03 Standart 8.5 / 5:
İçin sıfır-başlatmak tipi T aracının bir nesne:
- T, bir skaler tipi (3.9) ise, nesne (sıfır), 0 değerine ayarlanır T dönüştürülür;
- T bir birleştirici olmayan sınıf tipiyse, her statik olmayan veri elemanı ve her bir temel sınıf alt nesnesi sıfır başlatılır;
- T birleşim tipiyse, nesnenin ilk adlandırılmış veri üyesi sıfırdan başlatılır;
- T bir dizi tipiyse, her eleman sıfır başlangıç değerine ayarlanır;
- T referans tipiyse, başlatma yapılmaz.İçin varsayılan-başlatmak tipi T aracının bir nesne:
- T, bir POD olmayan sınıf tipi (bölüm 9) ise, T varsayılan yapıcı olarak adlandırılır (T hiçbir erişilebilir varsayılan kurucu varsa başlatma kötü oluşturulur);
- T bir dizi türüyse, her öğe varsayılan olarak başlatılır;
- aksi takdirde, nesne sıfırla başlatılır.İçin değer başlangıç durumuna tipi T aracının bir nesne:
- T, bir kullanıcı tarafından beyan kurucu (12.1) ile birlikte bir sınıf türü (bölüm 9) ise, o zaman T varsayılan yapıcı olarak adlandırılır (ve başlatma T ise kötü oluşturulur erişilebilir bir varsayılan kurucuya sahip değildir);
- T, kullanıcı tarafından bildirilmiş bir kurucu içermeyen bir birleşim olmayan sınıf tipiyse, T'nin statik olmayan her veri üyesi ve taban sınıfı bileşeni değerle başlatılır;
- T bir dizi türüyse, her öğe değerle başlatılır;
- aksi takdirde, nesne sıfırdan başlatılırReferans türündeki bir varlığın varsayılan olarak başlatılmasını veya değer başlatılmasını isteyen bir program yanlış biçimlendirilmiştir. T cv onaylı bir türse, sıfır başlatma, varsayılan başlatma ve değer başlatma gibi tanımlamalar için T'nin cv niteliksiz sürümü kullanılır.