Где в стандарте говорится, что инициализатор элемента по умолчанию для U:: j должен игнорироваться компилятором?
Рассмотрим следующий фрагмент:
#include <iostream>
union U{
U(): i(1) {}
int i;
int j = 2; // this default member initializer is ignored by the compiler
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
Код печатает (см. живой пример):
1
1
Где в стандарте говорится, что инициализатор элемента по умолчанию для члена U::j
игнорируется компилятором?
Обратите внимание, что объединение ниже не компилируется, и это нормально в соответствии с [class.union.anon]/4. Таким образом, я ожидал, что фрагмент выше также не компилируется.
Смотрите живой пример:
union U{
int i = 1;
int j = 2;
};
Ответы
Ответ 1
Где в стандарте говорится, что инициализатор элемента по умолчанию для члена U:: j игнорируется компилятором?
См. параграф 9 класса 9 [class.base.init] 9.1 на компакт-диске С++ 17.
N.B. ваше демо имеет поведение undefined, потому что активный член объединения i
, но вы читаете от j
. Это работает с некоторыми компиляторами как нестандартное расширение, но не допускается в ISO С++.
Ответ 2
Обратите внимание, что вы объявляете объект union, где все члены разделяют одну и ту же область памяти - переменные-члены переходят в разные "типизированные представления" тех же данных.
Таким образом, поскольку члены я и j эффективно сохраняются в одном и том же месте памяти, любая инициализация, выполняемая вами в j (с инициализатором), будет перезаписана вашим параметром конструктора i.
Просто для проверки удалите инициализацию я из конструктора:
#include <iostream>
union U{
U() {}
int i;
int j = 2; // this initializes both i & j
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
Выход будет
2
2
Обновление:
Согласно комментариям @Ayrosa и просто заинтригованным, я модифицировал оригинальный фрагмент, чтобы выполнить некоторую инициализацию с помощью функции (вместо константы), чтобы вызвать побочные эффекты.
#include <iostream>
int static someStatic()
{
std::cout << "Initializer was not ignored\n";
return(2);
}
union U{
U(): i(1) {}
int i;
int j = someStatic(); // this default member initializer is ignored by the compiler
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
Результат:
1
1
Значение, что вызов someStatic()
был фактически проигнорирован компилятором.