это отдельные понятия. Лучше не путать их так рано.

+ при использовании синтаксиса initializer_list для инициализации объекта обычные конструкторы объекта также участвуют в разрешении перегрузки, когда никакое другое правило инициализации списка не применяется. Насколько я понимаю, следующий код вызывает X :: X (int)

class X { int a_; X(int a):a_(a) {} );

void foo() {
   X bar{3};
}

Но я не понимаю, почему регулярные конструкторы также рассматриваются в контексте initializer_lists. Я чувствую, что многие программисты сейчас пишут X {3} для вызова конструктора вместо X (3) для вызова конструктора. Мне вообще не нравится этот стиль, так как он заставляет меня думать, что у объекта нет обычного конструктора.

По какой причине синтаксис initializer_list также можно использовать для вызова обычного конструктора? Есть ли причина сейчас предпочитать этот синтаксис обычным вызовам конструктора?

 user267210728 дек. 2017 г., 11:28
сейчас много программистов пишут X {3} да, это равномерная инициализация.
 Johannes Schaub - litb28 дек. 2017 г., 10:43
Причина в том, что они хотели, чтобы этот синтаксис работал практически для любого типа. Вы найдете, что это также работает для int и массивов. Нет никакой реальной причины предпочитать синтаксис старому испытанному синтаксису, если старый работает для вас.
 StoryTeller28 дек. 2017 г., 10:35
«Мне вообще не нравится этот стиль, так как он заставляет меня думать, что у объекта нет обычного конструктора» - Я бы не назвал это языковой проблемой.

Ответы на вопрос(1)

Решение Вопроса

диный способ инициализации объектов вместо нескольких подходов, в противном случае:

T v(args...); для обычного случаяT d = T(); при использовании конструктора по умолчанию для стековых объектовT m((iterator(x)), iterator()); бороться сMost Vexing Parse (обратите внимание на дополнительные скобки вокруг первого параметра)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

tl; dr: список инициализатора и унифицированный синтаксис инициализации - это две отдельные нотации. К сожалению, они конфликтуют.

 StoryTeller28 дек. 2017 г., 12:19
vu{{ 1, 2, 3 }}; недопустимо для c'tor, принимающегоstd::initializer_listи все же совершенно нормально для совокупности, какstd::array, Поговорим об исторических ошибках.
 Passer By12 мар. 2018 г., 09:10
Чтение этого делает меня грустным. Особенно, так как{1, 2} не имеет типа, еще вauto l = {1, 2}; l являетсяstd::initializer_list<int>, Заставляет меня задуматься, какую проблему решаетstd::initializer_list

Ваш ответ на вопрос