Страницы

Поиск по вопросам

понедельник, 24 декабря 2018 г.

Фигурная инициализация std::vector: множественные вложенные скобки

Такой код компилируется:
#include
int main(int argc, char* argv[]) { std::vector v2 = { { {} } }; std::vector v3 { { {} } }; std::vector v4 { { { 1 } } }; std::vector v5 ({ { { 1 } } });
return 0; }
Почему? Как интерпретируются множественные фигурные скобки? Если бы была одна пара скобок, это был бы initializer_list. А во что преобразуются три пары скобок? И почему именно три, а не больше (в GCC)? (Visual Studio 2013 допускает в этой ситуации произвольное количество скобок.)


Ответ

Все варианты используют конструктор std::vector, инициализирующий его из std::intializer_list, а четвертый вариант затем еще использует конструктор копирования вектора.
В данном случае наличие или отсутствие = в синтаксисе лист-инициализации в первых трех вариантах роли не играет, т.е. никакой разницы в семантике первых двух вариантов нет.
Вариант
std::vector v2 = { { {} } };
аналогичен
std::intializer_list temp_list = { {} }; std::vector v2 = { temp_list };
При этом {} является корректным инициализатором для объекта типа int, т.е.
std::intializer_list temp_list = { {} };
в свою очередь аналогично просто
int temp_int = {}; // инициализация нулем std::intializer_list temp_list = { temp_int }; Вариант
std::vector v3 { { {} } };
это, как уже говорилось выше, то же самое, только в синтаксисе прямой лист-инициализации. В варианте
std::vector v4 { { { 1 } } };
{ 1 } - вполне корректный инициализатор для объекта типа int. Т.е. этот вариант аналогичен
int temp_int = { 1 }; std::intializer_list temp_list = { temp_int }; std::vector v4 = { temp_list }; А вот вариант
std::vector v5 ({ { { 1 } } });
использует уже конструктор копирования класса std::vector, т.е. аналогичен
std::vector temp_vector = { { { 1 } } }; // см. вариант 3 std::vector v5(temp_vector);
Например, если мы объявим искусственный класс
struct S { S(std::initializer_list l) {} S(const S&) = delete; };
то первые три варианта прекрасно скомпилируются и для него, а вот четвертый - откажется компилироваться по причине удаленного конструктора копирования.
Попытки увеличивать количество скобок приводят к формированию неправильного инициализатора на самом нижнем уровне: ни { {} }, ни { { 1 } } уже не являются корректными инициализаторами для объекта типа int. Поэтому код не компилируется. Кстати, у меня и VS2015 отказывается компилировать варианты с увеличенным количеством скобок.

Комментариев нет:

Отправить комментарий