Рассмотрим следующее:
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;
}
Обратите внимание на использование foo.i
в списке агрегатов-инициализаторов.
g++ 5.2.0
выходы
45, 45
Является ли это четко определенным поведением? Является ли foo.i
в этом агрегаторе-инициализаторе всегда гарантировано ссылаться на созданный структурой элемент i
(и &foo.i
будет ссылаться на этот адрес памяти, например)?
Если я добавлю явный конструктор в mystruct
:
mystruct(int i, int j) : i(i), j(j) { }
Затем я получаю следующие предупреждения:
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;
Компиляция кода и выход:
45, 0
Ясно, что это делает что-то другое, и я предполагаю, что это поведение undefined. Это? Если да, то почему разница между этим и отсутствием конструктора? И как я могу получить начальное поведение (если это было четкое поведение) с определяемым пользователем конструктором?