我正在阅读C++0x 常见问题解答,并遇到了详细说明初始化程序列表的部分。这些示例主要是以下内容的变体:
vector<int> vi = { 1, 2, 3 };
vector<int> vj({1, 2, 3});
// etc.
但是,还列出了以下形式:
vector<int> vk{2};
这种形式出现在常见问题解答的其他地方,我很好奇它是否在语义上与最初的两种形式不同,或者只是vk({x, y, z})
.
我正在阅读C++0x 常见问题解答,并遇到了详细说明初始化程序列表的部分。这些示例主要是以下内容的变体:
vector<int> vi = { 1, 2, 3 };
vector<int> vj({1, 2, 3});
// etc.
但是,还列出了以下形式:
vector<int> vk{2};
这种形式出现在常见问题解答的其他地方,我很好奇它是否在语义上与最初的两种形式不同,或者只是vk({x, y, z})
.
该({1, 2, 3})
表单vector<int>
直接调用 的构造函数,并作为第一个参数 a 传递{1, 2, 3}
。你本可以传递更多参数
vector<int> vk({1, 2, 3}, myAllocator);
如果vector<int>
没有一个构造函数,其第一个参数是initializer_list
可以由{1, 2, 3}
(例如,另一个容器类)初始化的另一种类型,它将不起作用。在您的情况下,它可以工作,因为vector<int>
实际上有一个构造函数,其第一个参数是 a initializer_list<int>
。这就像在正常的函数调用中一样
void f(vector<int> const& vk);
int main() { f({1, 2, 3}); }
如果省略括号,如vector<int> vk{1, 2, 3}
,则确切含义取决于类。Avector<int>
有一个初始化列表构造函数,它是一个具有类型的第一个参数initializer_list<int>
(可选地对其的引用)以及所有其他具有默认参数的参数的构造函数。如果该类具有这样的构造函数,则初始化列表将传递给该构造函数。或者,该类可以简单地是一个聚合(例如struct A { int a; int b; int c; };
,初始化列表然后将初始化成员)或具有一个接受3
单独int
参数的构造函数。
最后,该= { 1, 2, 3 }
形式与省略括号的版本几乎相同(即仅删除=
),除了它禁止使用显式构造函数(即,他们将其声明为explicit vector(initializer_list<int>);
还是声明为 a explicit vector(int, int, int);
,如果使用 会导致错误= { 1, 2, 3 }
) .
一种是统一初始化,另一种是初始化列表。它们是两种不同的东西,尽管如您所见,它们可以产生相似的语法。
vector<int> vk{2};
是一个统一的初始化——另外两个是初始化列表。
统一初始化可防止缩小转换,即会导致数据丢失的转换:
#include <vector>
std::vector<float> v{1.0F, 2.0F, 3.0F}; // OK:
std::vector<float> w{1.0, 2.0, 3.0}; // OK: doubles could be put into floats without loss.
std::vector<int> j{1.1, 2.2, 3.3}; // error: narrowing
std::vector<int> k{1L, 2L, 3L}; // OK: the long numbers can be represented as int without loss.
std::vector<int> l{0xfacebeefL, 0xdeadbabeL, 0xfadecabeL}; // error: narrowing.