Inizializzazione predefinita di std :: array?


103

Con C ++ 11 std::array, ho la garanzia che la sintassi std::array<T, N> x;inizializzerà per impostazione predefinita tutti gli elementi dell'array?

EDIT : in caso contrario, esiste una sintassi che funzionerà su tutti gli array (inclusi gli array di dimensioni zero) per inizializzare tutti gli elementi al loro valore predefinito?

EDIT : su cppreference , la descrizione del costruttore predefinito dice:

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

quindi la risposta potrebbe essere sì. Ma vorrei esserne sicuro secondo lo standard o lo standard futuro.


Non credo proprio. È dichiarato predefinito, quindi è fondamentalmente l'equivalente della T x[N]sintassi.
Rapptz

Risposte:


148

Per definizione, l'inizializzazione predefinita è l'inizializzazione che si verifica quando non viene specificata nessun'altra inizializzazione; il linguaggio C ++ garantisce che qualsiasi oggetto per il quale non si fornisce un inizializzatore esplicito verrà inizializzato di default (C ++ 11 §8.5 / 11). Ciò include oggetti di tipo std::array<T, N>e T[N].

Tenere presente che ci sono tipi per i quali l'inizializzazione predefinita non ha effetto e lascia indeterminato il valore dell'oggetto: qualsiasi tipo non di classe, non di matrice (§8.5 / 6). Di conseguenza, un array di oggetti inizializzato di default con tali tipi avrà un valore indeterminato, ad esempio:

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

Sia l'array in stile c che quelli std::arraysono riempiti con numeri interi di valore indeterminato, proprio come plain_intha valore indeterminato.

Esiste una sintassi che funzioni su tutti gli array (inclusi gli array di dimensione zero) per inizializzare tutti gli elementi al loro valore predefinito?

Immagino che quando dici "al loro valore predefinito" intendi davvero "inizializza tutti gli elementi su T{}". Questa non è inizializzazione predefinita , è inizializzazione del valore (8.5 / 7). Puoi richiedere l'inizializzazione del valore abbastanza facilmente in C ++ 11 assegnando a ciascuna dichiarazione un inizializzatore vuoto:

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

Che inizializzerà a sua volta tutti gli elementi dell'array, risultando plain_old_inte tutti i membri di entrambi i tipi di array, inizializzati a zero.


E se fosse un membro di una classe: struct X {std :: array <int, 12> dozen; X (): dozen () {} Questo mi fa ottenere dodici zeri?
gerardw

4
@gerardw Secondo lo standard, sì. Attenzione ai bug in MSVC, non riesce a implementare correttamente alcuni casi di inizializzazione del valore.
Casey

1
infatti boost lo dice e risolverlo con il loro boost::value_initialized collegamento, ma credo che VC12 (VS2013) abbia un supporto molto migliore ora.
v.oddou

1
Mi fa desiderare che il comitato abbia modificato lo standard in inizializzazione del valore predefinito e minato il valore su richiesta. Vale a dire std :: array <int, 12> = {std :: indeterminato}; o qualcosa del genere
Viktor Sehr

In pratica cosa significa inizializzare qualcosa a un valore indeterminato? Qual è l'alternativa?
Andrew

21

Inizializzazione predefinita è un termine dello Standard che potenzialmente significa nessuna inizializzazione, quindi probabilmente intendi zero inizializzazione .

La descrizione su cppreference.com è in realtà un po 'fuorviante. std::arrayè una classe aggregata, e se il tipo di elemento è primitivo, è POD: "plain old data", con semantica che corrisponde strettamente al linguaggio C. Il costruttore implicitamente definito di std::array< int, N >è banale che non fa assolutamente nulla.

La sintassi simile std::array< int, 3 >()o std::array< int, 3 > x{}che fornisce valori azzerati non lo fa invocando un costruttore. Ottenere zeri fa parte dell'inizializzazione del valore , specificata in C ++ 11 §8.5 / 8:

Inizializzare un valore di un oggetto di tipo T significa:

- se T è un tipo di classe (possibilmente qualificato da cv) senza un costruttore predefinito fornito dall'utente o cancellato, l'oggetto è inizializzato zero ... e se T ha un costruttore predefinito non banale, l'oggetto è inizializzato per impostazione predefinita;

std::arraynon ha un costruttore predefinito fornito dall'utente, quindi viene inizializzato a zero. Ha un costruttore predefinito definito in modo implicito, ma è banale, quindi non viene mai inizializzato per impostazione predefinita. (Ma questo non fa differenza poiché l'inizializzazione banale per definizione non ha effetto in fase di esecuzione.)

in caso contrario, esiste una sintassi che funzionerà su tutti gli array (inclusi gli array di dimensioni zero) per inizializzare tutti gli elementi al loro valore predefinito?

Gli array in stile C std::arraysono entrambi aggregati e il modo per inizializzare completamente a zero qualsiasi aggregato è con la sintassi = {}. Funziona da C ++ 98. Notare che gli array in stile C non possono avere estensione zero e questo sizeof (std::array< X, 0 >)non è zero.


6

Entrambi T x[N];e std::array<T, N> x;inizializzano di default ogni elemento dell'array.

Ad esempio, se T = std::string, ogni elemento sarà una stringa vuota. Se Tè una classe senza un costruttore predefinito, entrambi non verranno compilati. If T = int, ogni elemento avrà un valore indeterminato (a meno che tale dichiarazione non si trovi nell'ambito dello spazio dei nomi)


0

Prima di tutto, T x [N] inizializza di default gli elementi, sebbene l'inizializzazione di default di un tipo scalare T in realtà non faccia nulla. Quanto sopra vale anche per std :: array x. Penso che ciò di cui hai bisogno sia l'inizializzazione dell'elenco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.