Инициализация списка. Что изменилось в С++ 14?

введите здесь описание изображенияЭти две строки из cppreference

В чем разница между этими двумя утверждениями? я не вижу никакой разницы

до С++14

Если список инициализации в фигурных скобках пуст и T является типом класса с конструктором по умолчанию, выполняется инициализация значения. В противном случае, если T является агрегатным типом, выполняется агрегатная инициализация.

начиная с C++14

Если T является агрегатным типом, выполняется агрегатная инициализация. В противном случае, если список инициализации в фигурных скобках пуст и T является типом класса с конструктором по умолчанию, выполняется инициализация значения.


person pvc    schedule 28.06.2020    source источник
comment
Спасибо @cigien и @StoryTeller за правки.   -  person pvc    schedule 28.06.2020


Ответы (2)


Разница заключается в том, какое из них происходит, когда применяются оба условия: если T является агрегатным классом (в отличие от массива), который, безусловно, имеет конструктор по умолчанию, и braced-init-list пуст. Конечно, чтобы понять, почему это важно, мы должны отличать инициализацию значения от агрегатной инициализации из пустого списка.

Инициализация значения инициализирует объект нулем, а затем инициализирует его по умолчанию, что для агрегата является инициализацией по умолчанию каждого из его членов, поэтому инициализация значения выполняется по элементам (плюс заполнение нулями). Агрегатная инициализация инициализирует каждый член из {}, что также является инициализацией значения для многих типов, но является инициализацией по умолчанию для членов типа класса с предоставленным пользователем конструктором по умолчанию. Разницу можно увидеть в

struct A {A() {} int i;};
struct B {A a;};  // aggregate
B b{};     // i is 0 in C++11, uninitialized in C++14
B b2=B();  // i is 0 in both versions

Только в C++14 агрегаты могут иметь инициализаторы элементов по умолчанию; это, конечно, не может способствовать различию в поведении между двумя языковыми версиями, но в любом случае оно не ведет себя по-разному между этими двумя правилами (поскольку оно заменяет только общую инициализацию по умолчанию).

person Davis Herring    schedule 28.06.2020
comment
Не все агрегаты имеют неудаляемый конструктор по умолчанию (например, struct X {const int x; };). - person T.C.; 28.06.2020
comment
@T.C.: Это правда, но вопрос о том, удален ли конструктор, здесь не рассматривается (за исключением того, что инициализация может быть неправильно сформирована). Или это ваша точка зрения, что инициализация такого типа с помощью {} неправильно сформирована в С++ 11, но не в С++ 14? - person Davis Herring; 28.06.2020
comment
В N3337 корректность зависит от того, является ли удаленный конструктор по умолчанию X тривиальным. — я думаю, что это согласно определению того времени . Если я правильно читаю вики-заметки, CWG1301 изменил определение инициализации значения, чтобы отклонить удаленные конструкторы, и переупорядочил пули, чтобы сохранить действительность {}. - person T.C.; 28.06.2020

Отличие заключается в последовательности проверки, поэтому в первую очередь происходит проверка агрегатного типа, а уже потом все остальное.

person Hack06    schedule 28.06.2020
comment
И на что влияет это изменение? - person Evg; 28.06.2020