Std :: array varsayılan olarak başlatılsın mı?


106

C ++ 11 ile std::array, sözdiziminin std::array<T, N> x;dizinin tüm öğelerini varsayılan olarak başlatacağına dair garantiye sahip miyim ?

DÜZENLEME : değilse, tüm öğeleri varsayılan değerlerine başlatmak için tüm dizilerde (sıfır boyutlu diziler dahil) çalışacak bir sözdizimi var mı?

DÜZENLEME : cppreference'de , varsayılan yapıcı açıklaması şunu söyler:

(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array 

bu yüzden cevap evet olabilir. Ancak standart veya gelecekteki standarda göre bundan emin olmak isterim.


Öyle düşünmeyin. Varsayılan olarak beyan edildiğinden, temelde T x[N]sözdiziminin eşdeğeridir .
Rapptz

Yanıtlar:


151

Tanım olarak, varsayılan başlatma, başka bir başlatma belirtilmediğinde gerçekleşen başlatmadır; C ++ dili , açık bir başlatıcı sağlamadığınız herhangi bir nesnenin varsayılan olarak başlatılacağını garanti eder (C ++ 11 §8.5 / 11). Bu tür nesneleri içerir std::array<T, N>ve T[N].

Varsayılan başlatmanın etkisinin olmadığı ve nesnenin değerini belirsiz bıraktığı türler olduğunu unutmayın: sınıf dışı, dizi olmayan tür (§8.5 / 6). Sonuç olarak, bu tür türlere sahip varsayılan olarak başlatılmış bir nesne dizisi belirsiz değere sahip olacaktır, örneğin:

int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;

Hem c-stil dizisi hem std::arrayde belirsiz değere sahip tamsayılarla doldurulur plain_int.

Tüm öğeleri varsayılan değerlerine başlatmak için tüm dizilerde (sıfır boyutlu diziler dahil) çalışacak bir sözdizimi var mı?

"Varsayılan değerlerine" dediğinizde, gerçekten "tüm öğeleri başlat" dediğinizde tahmin ediyorum T{}. Bu varsayılan başlatma değil, değer başlatma (8.5 / 7). C ++ 11'de her bildirime boş bir başlatıcı vererek değer başlatmayı oldukça kolay bir şekilde talep edebilirsiniz:

int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};

Bu, sırayla tüm dizi öğelerini değerle başlatacak plain_old_intve her iki tür dizinin tüm üyelerinin sıfıra başlatılmasına neden olacaktır.


Ya bir sınıf üyesi ise: struct X {std :: array <int, 12> düzine; X (): düzine () {} Bu bana on iki sıfır kazandırır mı?
gerardw

4
@gerardw Standarda göre evet öyle. MSVC'deki hatalara dikkat edin, bazı değer başlatma durumlarını doğru şekilde uygulayamaz.
Casey

1
gerçekten de boost öyle diyor ve kendi boost::value_initialized bağlantılarıyla geçici bir çözüm buluyor, ancak VC12'nin (VS2013) artık çok daha iyi bir desteğe sahip olduğuna inanıyorum.
v.oddou

1
Komitenin standardı varsayılan değer başlatma ve istek üzerine zayıflatılmış değere değiştirmesini dilememi sağlıyor. Yani std :: array <int, 12> = {std :: undetermined}; ya da bir şey
Viktor Sehr

Pratikte bir şeyi belirsiz bir değere başlatmak ne anlama gelir? Alternatif nedir?
Andrew

23

Varsayılan başlatma , Standarttan bir terimdir ve potansiyel olarak hiç başlatma olmadığı anlamına gelir, bu nedenle muhtemelen sıfır başlatmayı kastediyorsunuz .

Cppreference.com'daki açıklama aslında biraz yanıltıcıdır. std::arraykümelenmiş bir sınıftır ve öğe türü ilkel ise, C diliyle yakından eşleşen anlambilimle POD: "düz eski veriler" dir. Arasında örtük tanımlanmış yapıcı std::array< int, N >bir olan önemsiz kesinlikle hiçbir şey yapmaz biri.

Benzer std::array< int, 3 >()veya std::array< int, 3 > x{}sıfırlanmış değerler sağlayan sözdizimi , bir kurucu çağırarak bunu yapmaz. Sıfır elde etmek, C ++ 11 §8.5 / 8'de belirtilen değer başlatmanın bir parçasıdır :

T türünde bir nesneyi değerle başlatmak için şu anlama gelir:

- T, kullanıcı tarafından sağlanan veya silinmiş bir varsayılan kurucu olmadan (muhtemelen cv nitelikli) bir sınıf tipiyse, nesne sıfır olarak başlatılır… ve T, önemsiz olmayan bir varsayılan kurucuya sahipse, nesne varsayılan olarak başlatılır;

std::arraykullanıcı tarafından sağlanan varsayılan kurucu yoktur, bu nedenle sıfır başlatılır. Örtük olarak tanımlanmış bir varsayılan kurucuya sahiptir, ancak önemsizdir, bu nedenle hiçbir zaman varsayılan olarak başlatılmaz. (Ancak, tanım gereği önemsiz başlatmanın çalışma zamanında etkisi olmadığı için bu bir fark yaratmaz.)

değilse, tüm öğeleri varsayılan değerlerine başlatmak için tüm dizilerde (sıfır boyutlu diziler dahil) çalışacak bir sözdizimi var mı?

C-tarzı diziler ve std::arrayher ikisi de kümelerdir ve herhangi bir toplamayı tamamen sıfır başlatmanın yolu sözdizimidir = {}. Bu, C ++ 98'den beri çalışır. C tarzı dizilerin sıfır kapsamının sizeof (std::array< X, 0 >)olamayacağını ve bunun sıfır olmadığını unutmayın.


6

Both T x[N];ve std::array<T, N> x;dizinin her elemanını varsayılan olarak başlat.

Örneğin, eğer T = std::string, her eleman boş bir dizge olacaktır. Eğer Tbir sınıf varsayılan bir yapıcı olmadan, hem derleme başarısız olur. Eğer T = int, her eleman belirsiz değere sahip olacaksa (bu bildirim ad alanı kapsamında olmadıkça)


0

İlk olarak, T x [N] öğeleri varsayılan olarak başlatır, ancak bir skaler tip T'nin varsayılan olarak başlatılması aslında hiçbir şey yapmaz. Yukarıdakiler std :: array x için de geçerlidir. Sanırım ihtiyacın olan şey liste başlatmak.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.