В С++11 появился новый синтаксис инициализации. Вот что по этому поводу пишет Скотт Майерс в книге Effective Modern C++:
class Widget {
public:
Widget(); // default ctor
Widget(std::initializer_list<int> il); // std::initializer_list ctor
… // no implicit conversion funcs
};
Widget w1; // calls default ctor
Widget w2{}; // also calls default ctor
Widget w3(); // most vexing parse! declares a function!
Widget w4({}); // calls std::initializer_list ctor with empty list
Widget w5{{}}; // ditto
Если взять его пример, выкинуть лишнее, и добавить печать в конструктор Widget, то окажется что Widget w4({}); и Widget w5{{}}; это не одно и то же:
#include <iostream>
#include <initializer_list>
class Widget{
public:
Widget(){
}
Widget(std::initializer_list<int> l){
std::cout << "l.size = " << l.size() << std::endl;
}
};
int main(){
Widget w4({}); //l.size = 0
Widget w5{{}}; //l.size = 1
}
Пример
У меня два вопроса:
Widget(std::initializer_list<int> l)//Это initializer-list constructor
Следуя стандарту, он имеет приоритет над другими конструкторами в list-initialization.
Initializer-list constructors are favored over other constructors in list-initialization (16.3.1.7)
Widget w4({});
Это direct-initialization. Инициализатор - пустой std::initializer_list.
Widget w4{{}};
Это уже list-initialization. В данном случае direct-list-initialization.
Если список инициализации пуст, то выбирается конструктор по-умолчанию. Если же список инициализации не пуст, то конструктор выбирается в две фазы:
Initially, the candidate functions are the initializer-list constructors (11.6.4) of the class T and the argument list consists of the initializer list as a single argument
If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.
Начинаем первую фазу "ручного" поиска подходящего конструктора.
В первой фазе все аргументы рассматриваются как один initializer list.
Если рассмотреть скобочки в инициализаторе как создание std::initializer_list, то можно ли создать std::initializer_list<int>, передав ему {}?
Да, можно
std::initializer_list<int>{{/*вот он наш единственный int со значением 0*/}}`
Всё, подходящий конструктор найден.
То есть в нашем случае
Widget w5{{}};
//приведет к такому -->
Widget w5(std::initializer_list<int>{int{}});
Или еще примеры:
Widget w5{{1}, {2}};//-->
Widget w6(std::initializer_list<int>{int{1}, int{2}});
Widget w7{{1, 2}};//-->
Widget w8(std::initializer_list<int>{std::initializer_list<int>{1, 2}});
Старался объяснить как можно проще, поэтому, изложение "своими словами" может быть не совсем точным.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники