3

我正在阅读C++0x 常见问题解答,并遇到了详细说明初始化程序列表的部分。这些示例主要是以下内容的变体:

vector<int> vi = { 1, 2, 3 };
vector<int> vj({1, 2, 3});
// etc.

但是,还列出了以下形式:

vector<int> vk{2};

这种形式出现在常见问题解答的其他地方,我很好奇它是否在语义上与最初的两种形式不同,或者只是vk({x, y, z}).

4

3 回答 3

6

({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 }) .

于 2011-08-12T20:23:29.580 回答
1

一种是统一初始化,另一种是初始化列表。它们是两种不同的东西,尽管如您所见,它们可以产生相似的语法。

vector<int> vk{2};

是一个统一的初始化——另外两个是初始化列表。

于 2011-08-12T18:02:20.753 回答
0

统一初始化可防止缩小转换,即会导致数据丢失的转换:

#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.
于 2011-08-13T01:06:47.243 回答