【发布时间】:2017-10-08 18:54:18
【问题描述】:
在 C++ 中初始化对象(类或结构的实例)可以通过多种方式完成。一些语法唤起对象的直接初始化,其他语法导致复制初始化。在编译器中启用 copy-elision 后,两者具有相同的性能。禁用 copy-elision 后,当您选择后者(复制初始化)时,每次实例化都会调用额外的复制/移动构造函数。
结论:复制初始化会带来性能损失!
从以下问题:C++11 member initializer list vs in-class initializer? 我可以得出结论,这将是 copy-initialization 语法:
obj s = obj("value");
这将是直接初始化语法:
obj s{"value"};
但是这个呢:
obj s = {"value"};
还有这个:
obj s = obj{"value"};
还有这个:
obj s("value");
或者这个:
obj s = "value";
注意
Bjarne Stroustrup 在他的书“Programming, Principles and Practice Using C++”第 311 页第 9.4.2 节中比较了一些初始化样式(但不是全部):
struct Date { int y,m,d; //year, month, day Date(int y, int m, int d); //check for valid date and initialize void add_day(int n); //increase the Date by n days };...
Date my_birthday; //error: my_birthday not initialized Date today{12,24,2007}; //oops! run-time error Date last{2000,12,31}; //OK (colloquial style) Date next = {2014,2,14}; //also OK (slightly verbose) Date christmas = Date{1976,12,24}; //also OK (verbose style)
先生。 Stroustrup 将这些不同的初始化风格视为相同。至少,在我看来是这样的。尽管如此,仍然可能有一些是直接初始化,而另一些是复制初始化,因为本书当时还没有讨论这些术语。
编辑
给出的答案带来了一些有趣的东西。
显然,这是直接初始化:
obj s("value");
这是直接列表初始化:
obj s{"value"};
正如你们中的一些人所指出的,这是有区别的。它们实际上有什么不同?在非优化编译器的输出中,差异会很明显吗?
【问题讨论】:
-
有
=吗?是的:这是复制初始化。否则直接初始化。 -
@Rakete1111 That doesn't seem to be true.
-
@nwp 当然,如果你使用大括号,它是*-list-initialization,取决于
=。对不起,谢谢! -
@nwp copy-list-initialization 在技术上是根据 [dcl.init] 中的措辞的一种复制初始化类型,即使它们具有不同的语义(尤其是复制列表初始化类类型不一定依赖于移动/复制构造函数)。
-
我们还没有一个规范的“初始化东西的所有不同方法以及何时有副本”的问题吗?也许我们也应该制作一个涵盖 C++17 的内容。
标签: c++ c++11 initialization c++14 initializer-list