<分区>
在初始化自动管理的简单变量时,除了通过赋值之外,还有几种不同的样式。我想知道是否有任何特定的理由偏爱其中一个,还是仅仅是风格问题。
使用括号很吸引人,因为它感觉类似于实例化一个对象
double answer(42.0);
ComplexNumber i(0,1);
虽然使用大括号很吸引人,因为它感觉类似于初始化容器
double answer{42};
std::vector<double> i{0,1};
double i2[] = {0,1};
是否有任何特别的理由偏爱一种风格而不是另一种风格?
看这里:GotW #1 : Variable Initialization .这是对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 };
或 auto v = vector<int>{ 1, 2, 3, 4 };
,因为它更一致,更正确,并且完全避免了必须了解旧式陷阱。在您希望只看到 =
的单参数情况下符号,例如 int i = 42
;和 auto x = anything
;省略大括号是可以的。
我们可以使用 ()-initialization 来显式调用特殊构造函数。