Формы инициализации списка

См. следующий код:

std::vector<int> v1{1, 2, 3};
std::vector<int> v2 = {1, 2, 3};

Мои вопросы:

  1. Есть ли разница между ними? Я знаю, что первое должно быть инициализацией списка, но как насчет второго?

  2. Поскольку для второго есть знак назначения, это заставляет меня думать, что компилятор сначала будет использовать std::initializer_list для создания временного vector, а затем использовать конструктор копирования для копирования временного vector в v2. Это факт?


person zhangzhimin    schedule 26.07.2016    source источник


Ответы (2)


Два (direct-list-initialization и copy- list-initialization) в этом случае точно такие же. Временный std::vector не создается и std::vector::operator= не вызывается. Знак равенства является частью синтаксиса инициализации.

Была бы разница, если бы перегрузка конструктора std::vector была перегружена. 7 был помечен explicit, и в этом случае любая инициализация копирования завершается ошибкой, но это было бы недостатком в структуре стандартной библиотеки.

person LogicStuff    schedule 26.07.2016
comment
Итак, оба относятся к инициализации списка, они не связаны с инициализацией копии, верно? - person zhangzhimin; 26.07.2016
comment
инициализация-копии-списка определяется в терминах копии-инициализации. Я использовал copy-initialization просто для того, чтобы немного обобщить. - person LogicStuff; 26.07.2016

Оба они являются инициализацией списка (начиная с C++11). Первый — это прямая инициализация списка, а второй — инициализация списка копирования.

  1. Есть ли разница между ними?

Для прямой-списковой-инициализации будут рассматриваться как явные, так и неявные конструкторы, в то время как для копирования-списка-инициализации могут вызываться только неявные конструкторы. Для этого случая (т.е. std::vector) фактический результат такой же.

  1. Поскольку для второго есть знак назначения, это заставляет меня думать, что компилятор сначала будет использовать initializer_list для создания временного вектора, а затем использовать конструктор копирования для копирования временного вектора в v2. Это факт?

Нет. Даже для инициализации списка копирования объект будет построен соответствующим конструктором напрямую. В этом случае будет создан временный std::initializer_list<int>, а затем будет вызван std::vector::vector(std::initializer_list<T>, const Allocator& = Allocator()) для построения v2.

person songyuanyao    schedule 26.07.2016
comment
Интересно добавить, что в C++17 может быть по-другому, если вы используете auto и список только с одним элементом. - person EFenix; 26.07.2016
comment
@AntonioGarrido нет, не будет. auto v = {1} никогда не выводил std::vector. Действительно, теперь он будет выводить int вместо std::initializer_list, но совершенно не имеет отношения к обсуждению std::vector. - person bolov; 26.07.2016
comment
@AntonioGarrido, если вы хотите обсудить C ++ 17 и auto, может быть несколько уместно, что вы сможете написать auto v = vector{1, 2, 3} (вывод шаблона для конструктора) - person bolov; 26.07.2016
comment
@bolov ИМХО, актуально. В ответе несколько выражено, что использование = или нет имеет значение только в отношении неявной/явной конструкции, но в С++ 17 добавляется еще один аспект: это не то же самое. См., например, вывод типа С++ и почему вас это волнует, Скотт Мейерс, слайд 20. Ваша строка о выводе шаблона для конструктора не связана с этим обсуждением (это обсуждение в этом ответе, где прямая-список-инициализация против копи-списка- инициализация обсуждается). В любом случае, я нажал на флажок вашего комментария. Мне нравится, когда люди запоминают мою неточность. Спасибо! - person EFenix; 26.07.2016
comment
@AntonioGarrido просто любопытство: какой флаг вы подняли с моим комментарием? - person bolov; 26.07.2016
comment
Type val = { ... }; и Type val { ... }; в любом случае абсолютно одинаковы. - person Andrei R.; 26.07.2016
comment
@АндрейР. Нет, в некоторых случаях они не совпадают. Я объяснил это в своем ответе, вы можете указать, где я ошибаюсь. - person songyuanyao; 26.07.2016