直接列表初始化和复制列表初始化之间的差异

时间:2018-05-19 05:32:57

标签: c++ c++11 initialization c++14 c++17

我想知道C ++ 11及更高版本中以下两种类型的std::vector初始化是否有任何区别。

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的示例使用第二种,所以这让我想到这种初始化是否有任何优势。

一般来说,我想知道一个初始化是否具有相对于另一个的特定技术优势,或者如果一个初始化被认为是最佳实践,而另一个初始被认为是最佳实践,如果是,那么为什么。

特别是,我关注的是复制列表初始化是否因临时对象和复制而产生额外开销?

2 个答案:

答案 0 :(得分:11)

列表初始化被非正式地称为“统一初始化”,因为它的含义和行为旨在与相同,无论你如何调用它。

因此,直接列表初始化和复制列表初始化的行为之间只有一个区别:如果列表初始化将调用标记为explicit的构造函数,如果列表初始化表单是copy-list-initialization,则会出现编译错误。这是唯一的区别。

[dcl.list.init]解释了direct-list和copy-list之间的语法差异。也就是说,它描述了哪种形式的列表初始化是直接与复制。但它从未在两者之间定义任何功能差异

定义行为差异的标准的唯一部分是[over.match.list]/1

  

在copy-list-initialization中,如果选择了explicit构造函数,则初始化是不正确的。

这是重载解析的功能。

由于标准没有定义任何行为差异,如果编译器决定在它们之间施加一些功能差异,我会感到非常惊讶。

答案 1 :(得分:6)

我非常喜欢复制列表初始化(特别是在std::vector的情况下),因为直接列表初始化与std::vector的显式构造函数非常相似只有一两个要素。

std::vector<int> x(2);
// is very different from
std::vector<int> x{2};

明确指出我为向量分配初始值而不是使用值对其进行配置这一事实不太容易被误读。