用于初始化单个变量的 C++ 样式

Dun*_*ter 5 c++ coding-style initialization c++11

在初始化自动管理的简单变量而不是通过赋值时,有几种不同的风格。我想知道是否有任何特定的理由偏爱一个而不是另一个,或者这只是一个风格问题。

使用括号很有吸引力,因为它感觉类似于实例化一个对象

double answer(42.0);
ComplexNumber i(0,1);
Run Code Online (Sandbox Code Playgroud)

虽然使用大括号很有吸引力,因为它感觉类似于初始化容器

double answer{42};
std::vector<double> i{0,1};
double i2[] = {0,1};
Run Code Online (Sandbox Code Playgroud)

有什么特别的理由偏爱一种风格而不是另一种风格吗?

Bor*_*ris 4

看这里:GotW #1:变量初始化。这是 H. Sutter 答案的详细描述。

\n\n

H. Sutter 上面谈到了变量初始化的新旧风格的一般意义。

\n\n

下面根据您的起始主题上下文显示了本文的快速摘要。

\n\n
\n\n

这对

\n\n
double answer(42.0); // (1)\ndouble answer{42};  // (2)\n
Run Code Online (Sandbox Code Playgroud)\n\n

事实上,类似于下面的初始化示例:

\n\n
widget w(x);                // (d)\nwidget w{x};                // (e)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这些都是直接初始化。但请注意,该语法{x}会创建一个initializer_list. 如果widget有一个采用 的构造函数initializer_list,则首选该构造函数;否则,如果widget有一个采用任何类型的构造函数x(可能带有转换),则使用该构造函数。

\n\n

(2, e) 优于 (1, d) 有两个主要区别:

\n\n
    \n
  • 首先,语法 (2, e) 是明确的并且避免了“令人烦恼的解析”。如果x是类型名称,则 (1, d) 是函数声明,即使x作用域中还存在命名的变量(见上文),而 (2, e) 绝不是函数声明。
  • \n
  • 其次,语法 (2, e) 更安全,因为它不允许缩小(又名 \xe2\x80\x9clossy\xe2\x80\x9d)转换,而某些内置类型则允许这种转换。考虑:

    \n\n

    int i1( 12.345 ); // ok: toss .345, we didn\'t like it anyway

    \n\n

    int i2{ 12.345 }; // error: would be lossy implicit narrowing

  • \n
\n\n

下一对

\n\n
ComplexNumber i(0,1); // (3)\nstd::vector<double> i{0,1}; // (4)\n
Run Code Online (Sandbox Code Playgroud)\n\n

与复杂对象的初始化相关。两者看起来完全相同,但第二个可以帮助我们避免“令人烦恼的解析”,例如:

\n\n
ComplexNumber       w( real(), img() );       // oops, vexing parse \n
Run Code Online (Sandbox Code Playgroud)\n\n

除此之外,这种方式使代码更加清晰(如果我们使用initializer_list,初始化会更清晰),而且在某些情况下可以减轻语法,例如:

\n\n
draw_rect({ origin, selection });                  // C++11\n
Run Code Online (Sandbox Code Playgroud)\n\n

Sutter 的原则是:更喜欢使用 初始化{ },例如vector<int> v = { 1, 2, 3, 4 };auto v = vector<int>{ 1, 2, 3, 4 };,因为它\xe2\x80\x99 更一致、更正确,并且完全避免了了解旧式陷阱。在单参数情况下,您更愿意只看到符号=,例如int i = 42;和auto x = anything; 省略大括号就可以了。

\n\n

我们可以使用 () 初始化来显式调用特殊构造函数。

\n

  • 优秀的外部参考,但您的答案有被视为“仅链接”答案的危险。如果你能快速概括一下 Herb Sutter 所说的内容(粗略地说,如果你有 C++11 并且不必移植到不太现代的编译器,每次都使用“{}”符号以避免“最令人烦恼的解析”)。 (2认同)