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

315
22 июня 2017, 05:39

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

#include <vector>
int main(int argc, char* argv[])
{
  std::vector<int> v2 = { { {} } };
  std::vector<int> v3 { { {} } };
  std::vector<int> v4 { { { 1 } } };
  std::vector<int> v5 ({ { { 1 } } });
  return 0;
}

Почему? Как интерпретируются множественные фигурные скобки? Если бы была одна пара скобок, это был бы initializer_list. А во что преобразуются три пары скобок? И почему именно три, а не больше (в GCC)? (Visual Studio 2013 допускает в этой ситуации произвольное количество скобок.)

Answer 1

Все варианты используют конструктор std::vector<int>, инициализирующий его из std::intializer_list<int>, а четвертый вариант затем еще использует конструктор копирования вектора.

В данном случае наличие или отсутствие = в синтаксисе лист-инициализации в первых трех вариантах роли не играет, т.е. никакой разницы в семантике первых двух вариантов нет.

  1. Вариант

    std::vector<int> v2 = { { {} } };
    

    аналогичен

    std::intializer_list<int> temp_list = { {} };
    std::vector<int> v2 = { temp_list };
    

    При этом {} является корректным инициализатором для объекта типа int, т.е.

    std::intializer_list<int> temp_list = { {} };
    

    в свою очередь аналогично просто

    int temp_int = {}; // инициализация нулем
    std::intializer_list<int> temp_list = { temp_int };
    
  2. Вариант

    std::vector<int> v3 { { {} } };
    

    это, как уже говорилось выше, то же самое, только в синтаксисе прямой лист-инициализации.

  3. В варианте

    std::vector<int> v4 { { { 1 } } };
    

    { 1 } - вполне корректный инициализатор для объекта типа int. Т.е. этот вариант аналогичен

    int temp_int = { 1 };
    std::intializer_list<int> temp_list = { temp_int };
    std::vector<int> v4 = { temp_list };
    
  4. А вот вариант

    std::vector<int> v5 ({ { { 1 } } });
    

    использует уже конструктор копирования класса std::vector<int>, т.е. аналогичен

    std::vector<int> temp_vector = { { { 1 } } }; // см. вариант 3
    std::vector<int> v5(temp_vector);
    

    Например, если мы объявим искусственный класс

    struct S
    {
      S(std::initializer_list<int> l) {}
      S(const S&) = delete;
    }; 
    

    то первые три варианта прекрасно скомпилируются и для него, а вот четвертый - откажется компилироваться по причине удаленного конструктора копирования.

Попытки увеличивать количество скобок приводят к формированию неправильного инициализатора на самом нижнем уровне: ни { {} }, ни { { 1 } } уже не являются корректными инициализаторами для объекта типа int. Поэтому код не компилируется. Кстати, у меня и VS2015 отказывается компилировать варианты с увеличенным количеством скобок.

READ ALSO
C++ convert list&lt;wstring&gt; to PVOID

C++ convert list<wstring> to PVOID

Здравствуйте

285
Как найти позицию подстроки в строке?

Как найти позицию подстроки в строке?

Ищу наличие подстроки в строке, но не знаю, как сделать это правильноНапример, мне нужна позиция substring в string

372
Установка apk без использования adb

Установка apk без использования adb

как работать с подключенным по USB Андроид устройством? К примеру, как не используя adb установить apk в устройство, либо запуллить туда что-то?...

366