По сути это бардак. Для C++11 была предпринята попытка создать один единый способ инициализации объектов вместо нескольких подходов, необходимых в противном случае:
T v(args...);
для обычного случая
T d = T();
при использовании конструктора по умолчанию для объектов на основе стека
T m((iterator(x)), iterator());
для борьбы с самым неприятным анализом (обратите внимание на дополнительные скобки вокруг первого параметра)
T a = { /* some structured values */ };
для агрегатной инициализации
Вместо этого был изобретен унифицированный синтаксис инициализации:
T u{ /* whatever */ };
Намерение состояло в том, что везде будет использоваться единый синтаксис инициализации, а старый стиль выйдет из моды. Все было хорошо, кроме того, что сторонники инициализации из std::initializer_list<S>
поняли, что синтаксис будет примерно таким:
std::vector<int> vt({ 1, 2, 3 });
std::vector<int> vu{{ 1, 2, 3 }};
Это было сочтено неприемлемым, и единый синтаксис инициализации был непоправимо скомпрометирован, чтобы обеспечить намного лучшее
std::vector<int> vx{ 1, 2, 3 };
Проблема с этой смесью в том, что теперь иногда неясно, что на самом деле имеется в виду, и единый синтаксис инициализации больше не является единым. Это по-прежнему необходимо в некоторых контекстах (особенно для инициализации объектов на основе стека в универсальном коде), но это не правильный выбор во всех случаях. Например, следующие два обозначения должны были означать одно и то же, но это не так:
std::vector<int> v0(1, 2); // one element with value 2
std::vector<int> v1{1, 2}; // two elements: 1 and 2
Вкратце: список инициализаторов и унифицированный синтаксис инициализации — это две отдельные записи. К сожалению, они конфликтуют.
person
Dietmar Kühl
schedule
28.12.2017