Страницы

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

вторник, 31 декабря 2019 г.

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

#cpp #cpp11 #cpp14


Такой код компилируется:

#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 допускает в этой ситуации произвольное
количество скобок.)
    


Ответы

Ответ 1



Все варианты используют конструктор 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 отказывается компилировать варианты с увеличенным количеством скобок.

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

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