看这里:GotW #1:变量初始化。这是对 H. Sutter 回答的详细描述。
H. Sutter 在上面谈到了变量初始化的新旧风格的一般意义。
根据您的起始主题上下文,下面显示了文章的简要概要。
这对
double answer(42.0); // (1)
double answer{42}; // (2)
实际上,类似于下一个初始化示例:
widget w(x); // (d)
widget w{x}; // (e)
这些都是直接初始化。但是,请注意,该语法{x}
会创建一个initializer_list
. 如果widget
有一个带有 的构造函数,initializer_list
则首选该构造函数;否则,如果widget
有一个采用任何类型的构造函数x
(可能带有转换),则使用该构造函数。
有两个主要区别使得 (2, e) 优于 (1, d):
- 首先,语法 (2, e) 是明确的并且避免了“令人烦恼的解析”。如果
x
是类型名称,则 (1, d) 是函数声明,即使x
在范围内还有一个变量(见上文),而 (2, e) 绝不是函数声明。
其次,语法 (2, e) 更安全,因为它不允许缩小(也称为“有损”)转换,否则某些内置类型会允许这种转换。考虑:
int i1( 12.345 ); // ok: toss .345, we didn't like it anyway
int i2{ 12.345 }; // error: would be lossy implicit narrowing
下一对
ComplexNumber i(0,1); // (3)
std::vector<double> i{0,1}; // (4)
与复杂对象的初始化有关。两者看起来完全一样,但第二个帮助我们避免“恼人的解析”,比如:
ComplexNumber w( real(), img() ); // oops, vexing parse
除此之外,这种方式使代码更清晰(如果我们使用initializer_list
,则更清楚的是初始化),此外,在某些情况下还可以减轻语法,例如:
draw_rect({ origin, selection }); // C++11
Sutter 的准则是:更喜欢使用 初始化{ }
,例如vector<int> v = { 1, 2, 3, 4 };
or auto v = vector<int>{ 1, 2, 3, 4 };
,因为它更一致、更正确,并且完全避免了了解旧式陷阱。在您希望只看到符号的单参数情况下=
,例如int i = 42
; 和auto x = anything
; 省略括号很好。
我们可以使用 () 初始化来显式调用特殊构造函数。