Inicialização padrão de std :: array?

103

Com o C ++ 11 std::array, tenho a garantia de que a sintaxe std::array<T, N> x;inicializará por padrão todos os elementos da matriz?

EDIT : se não, existe uma sintaxe que funcionará em todas as matrizes (incluindo matrizes de tamanho zero) para inicializar todos os elementos com seu valor padrão?

EDIT : em cppreference , a descrição do construtor padrão diz:

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

então a resposta pode ser sim. Mas eu gostaria de ter certeza disso de acordo com o padrão ou padrão futuro.

Vincent
fonte
Acho que não. É declarado por padrão, então é basicamente o equivalente da T x[N]sintaxe.
Rapptz de

Respostas:

148

Por definição, a inicialização padrão é a inicialização que ocorre quando nenhuma outra inicialização é especificada; a linguagem C ++ garante que qualquer objeto para o qual você não forneça um inicializador explícito será inicializado por padrão (C ++ 11 §8.5 / 11). Isso inclui objetos do tipo std::array<T, N>e T[N].

Esteja ciente de que existem tipos para os quais a inicialização padrão não tem efeito e deixa o valor do objeto indeterminado: qualquer tipo sem classe, sem array (§8.5 / 6). Consequentemente, uma matriz de objetos inicializada por padrão com tais tipos terá valor indeterminado, por exemplo:

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

Tanto o array de estilo c quanto std::arraysão preenchidos com inteiros de valor indeterminado, assim como plain_inttem valor indeterminado.

Existe uma sintaxe que funcionará em todas as matrizes (incluindo matrizes de tamanho zero) para inicializar todos os elementos com seu valor padrão?

Estou supondo que quando você diz "para o valor padrão", você realmente quer dizer "inicializar todos os elementos para T{}". Isso não é inicialização padrão , é inicialização de valor (8.5 / 7). Você pode solicitar a inicialização de valor facilmente em C ++ 11, fornecendo a cada declaração um inicializador vazio:

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

O que inicializará o valor de todos os elementos do array por sua vez, resultando em plain_old_int, e todos os membros de ambos os tipos de arrays, sendo inicializados para zero.

Casey
fonte
E se for um membro da classe: struct X {std :: array <int, 12> dozen; X (): dozen () {} Isso me dá doze zeros?
gerardw,
4
@gerardw De acordo com o padrão, sim. Cuidado com os bugs do MSVC, ele falha ao implementar alguns casos de inicialização de valor corretamente.
Casey
1
na verdade, boost diz e contorne -o com seu boost::value_initialized link, mas acredito que VC12 (VS2013) tem um suporte muito melhor agora.
v.oddou
1
Faz-me desejar que o comitê altere o padrão para inicialização de valor padrão e valor minado a pedido. Ou seja, std :: array <int, 12> = {std :: undetermined}; ou algo assim
Viktor Sehr
Na prática, o que significa inicializar algo com um valor indeterminado? Qual é a alternativa?
Andrew
21

Inicialização padrão é um termo do padrão que significa potencialmente nenhuma inicialização, então você provavelmente quer dizer inicialização zero .

A descrição em cppreference.com é um pouco enganosa. std::arrayé uma classe agregada, e se o tipo de elemento for primitivo, é POD: "plain old data", com semântica que se aproxima da linguagem C. O construtor implicitamente definido de std::array< int, N >é um construtor trivial que não faz absolutamente nada.

A sintaxe como std::array< int, 3 >()ou std::array< int, 3 > x{}que fornece valores zerados não o faz invocando um construtor. Obter zeros faz parte da inicialização de valor , especificada em C ++ 11 §8.5 / 8:

Inicializar o valor de um objeto do tipo T significa:

- se T é um tipo de classe (possivelmente qualificado pelo cv) sem um construtor padrão fornecido pelo usuário ou excluído, então o objeto é inicializado com zero ..., e se T tem um construtor padrão não trivial, o objeto é inicializado por padrão;

std::arraynão tem um construtor padrão fornecido pelo usuário, portanto, é inicializado com zero. Ele tem um construtor padrão definido implicitamente, mas é trivial, portanto, nunca é inicializado por padrão. (Mas isso não faz diferença, pois a inicialização trivial, por definição, não tem efeito no tempo de execução.)

se não, existe uma sintaxe que funcionará em todos os arrays (incluindo arrays de tamanho zero) para inicializar todos os elementos com seu valor padrão?

Matrizes de estilo C e std::arraysão agregados, e a maneira de inicializar completamente com zero qualquer agregado é com a sintaxe = {}. Isso funciona desde C ++ 98. Observe que os arrays de estilo C não podem ter extensão zero, e isso sizeof (std::array< X, 0 >)não é zero.

Potatoswatter
fonte
6

Ambos T x[N];e std::array<T, N> x;inicializam por padrão todos os elementos da matriz.

Por exemplo, se T = std::string, cada elemento será uma string vazia. Se Tfor uma classe sem um construtor padrão, ambos falharão ao compilar. Se T = int, cada elemento terá um valor indeterminado (a menos que essa declaração esteja no escopo do namespace)

Cubbi
fonte
0

Em primeiro lugar, T x [N] inicializa os elementos por padrão, embora a inicialização padrão de um tipo escalar T na verdade não faça nada. O acima também é válido para std :: array x. Acho que você precisa é de inicialização de lista.

Lingxi
fonte