É um comportamento definido fazer referência a um membro inicial de uma expressão de membro posterior durante a inicialização agregada?
Considere o seguinte:
struct mystruct
{
int i;
int j;
};
int main(int argc, char* argv[])
{
mystruct foo{45, foo.i};
std::cout << foo.i << ", " << foo.j << std::endl;
return 0;
}
Observe o uso defoo.i
na lista agregador-inicializador.
g++ 5.2.0
saídas
45, 45
Esse comportamento é bem definido? Éfoo.i
neste inicializador agregado sempre garantido para se referir à estrutura que está sendo criadai
elemento (e&foo.i
se referiria a esse endereço de memória, por exemplo)?
Se eu adicionar um construtor explícito aomystruct
:
mystruct(int i, int j) : i(i), j(j) { }
Então, recebo os seguintes avisos:
main.cpp:15:20: warning: 'foo.a::i' is used uninitialized in this function [-Wuninitialized]
a foo{45, foo.i};
^
main.cpp:19:34: warning: 'foo.a::i' is used uninitialized in this function [-Wuninitialized]
cout << foo.i << ", " << foo.j << endl;
O código é compilado e a saída é:
45, 0
Claramente, isso faz algo diferente, e estou assumindo que esse seja um comportamento indefinido. É isso? Se sim, por que a diferença entre isso e quando não havia construtor? E, como posso obter o comportamento inicial (se fosse um comportamento bem definido) com um construtor definido pelo usuário?