Подтвердить что ты не робот

Где в стандарте говорится, что инициализатор элемента по умолчанию для 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;
};
4b9b3361

Ответ 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() был фактически проигнорирован компилятором.