列表初始化和复制删除
List initialization and copy elision
考虑以下示例:
#include <cstdlib>
struct A
{
A(int, char*){};
A(const A&){ printf("copy-ctorn"); }
};
int main()
{
A x = A(5, nullptr);
}
根据(c++ 11标准的)8.5.16,
A x = A(5, nullptr);
被视为
A x(A(5, nullptr));
(即。然后根据12.8.31编译器允许(但不强制)执行一个称为"复制省略"的优化,以消除创建a类型的临时对象,从而有效地使那行代码变成
。 A x(5, nullptr);
(即。没有创建临时变量,没有调用复制函数)。
现在,假设我在上面的例子中使用了一个列表初始化: A x = {5, nullptr}; // (1)
或
A x = A{5, nullptr}; // (2)
谁能从c++ 11标准中引用适当的段落来证实或否认(1)和/或(2)将总是(即不仅当编译器可以做"复制省略"优化时)被视为
A x(5, nullptr);
(即。直接调用A的第一个构造函数,不创建临时对象,不复制A类型的对象)。
这个答案显然是错误的,这让我很惊讶。请看评论。我认为[dcl.init]的第一个和第四个要点。
表示(1)直接调用构造函数(或执行聚合初始化),而不需要临时调用。标准中没有任何内容保证(1)和(2)避免临时的。它们都是复制初始化,(1)是由[dcl.init]定义的复制列表初始化。列表]p1:
list初始化可以发生在直接初始化或复制初始化上下文中;直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化。
在这两种情况下都是复制初始化,而[dcl。Init]表示可能涉及移动(可以省略)。
8.5/14,15
:
以
形式出现的初始化
T x = a;
[…]称为复制初始化。
表单
中的初始化
T x(a);
T x{a};
[…]称为直接初始化。
如果你的编译器不够聪明,不能总是省略临时,那么为了确保列表初始化没有临时,你可以使用直接列表初始化,即
A x{5, nullptr};
相关文章:
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- std::ofstream 作为类成员删除复制构造函数?
- 删除复制构造函数的 Intel 13.1.2 中不良C++行为的解决方法
- c++17在编译时将带有已删除复制构造函数的类添加到std::vector
- 删除复制构造函数是否也会删除默认的复制/移动运算符?
- 用于删除复制/移动分配运算符的有效签名
- 为什么在具有引用字段的类中隐式删除复制运算符
- 为什么当类具有引用成员时C++编译器不删除复制构造函数
- 删除复制构造函数和运算符=类范围访问
- 是否可以使用 lambda 初始化变量(删除复制 ctor 时)
- 删除复制和复制转让 - 公共、私有还是受保护?
- 是否可以在基类中删除复制和移动构造函数/分配运算符
- 为什么具有已删除复制构造函数的结构不是 POD 类型
- 为什么删除复制构造函数会影响用户定义的默认构造函数?
- 带有向量的unique_ptr:错误:xxx的隐式删除复制构造函数
- 当提供用户定义的移动构造函数时,Visual Studio 2013不会删除复制构造函数
- 删除复制构造函数或复制赋值运算符算"user declared"吗?
- 为什么我们需要删除复制赋值运算符中的指针
- 卸载程序不会删除复制到VS2010安装程序项目中的系统文件夹。