Различия между инициализацией прямого списка и инициализацией списка копий
Я хотел бы знать, есть ли разница в следующих двух типах инициализации std::vector
в С++ 11 и более поздних версиях.
std::vector<int> v1 {1, 2, 3, 4, 5};
std::vector<int> v2 = {1, 2, 3, 4, 5};
Вот полный пример кода, который отлично работает.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v1 {1, 2, 3, 4, 5};
std::vector<int> v2 = {1, 2, 3, 4, 5};
std::cout << v1.size() << '\n';
std::cout << v2.size() << '\n';
}
Я вижу обе инициализации, приводящие к одинаковым результатам.
Пример в http://en.cppreference.com/w/cpp/container/vector использует второй тип, поэтому я подумал, имеет ли такая инициализация какое-либо преимущество.
В общем, я хочу знать, имеет ли одна инициализация конкретное техническое преимущество над другим, или если одна инициализация считается лучшей практикой, а другая - нет, и если да, то почему.
В частности, меня беспокоит, есть ли у инициализации списка копий дополнительные накладные расходы из-за временных объектов и копирования?
Ответы
Ответ 1
Инициализация списка неофициально называется "равномерной инициализацией", поскольку ее значение и поведение должны быть одинаковыми независимо от того, как вы его вызываете.
Таким образом, существует только одно различие между поведением инициализации прямого списка и инициализацией списка копий: если инициализация списка вызовет конструктор, помеченный как explicit
, то возникает ошибка компиляции, если форма списка-списка является копией -list инициализация. Это единственное различие.
[dcl.list.init] объясняет синтаксическую разницу между прямым списком и списком копий. То есть он описывает, какие формы инициализации списка являются прямыми и копиями. Но он никогда не определяет функциональную разницу между ними.
Единственная часть стандарта, которая определяет поведенческую разницу, находится в [over.match.list]/1:
В инициализации списка копий, если выбран explicit
конструктор, инициализация плохо сформирована.
Это функция разрешения перегрузки.
Поскольку стандарт не определяет поведенческую разницу, я был бы очень удивлен, если бы компиляторы решили наложить на них некоторую функциональную разницу.
Ответ 2
Я очень предпочитаю инициализацию копирования списка в целом (и особенно в случае std::vector
), так как инициализация прямой список очень похож на взгляд std::vector
явных конструкторов, когда есть только один или два элемента.
std::vector<int> x(2);
// is very different from
std::vector<int> x{2};
Явное указание на то, что я назначаю начальное значение вектору и не настраивая его со значениями, менее подвержено ошибкам.