为什么不调用复制构造函数将临时对象复制到新定义的对象
Why Copy constructor is NOT called to copy the temporary object to the new defined object
#include <iostream>
using namespace std;
class Y {
public:
Y(int ) {
cout << "Y(int)n";
}
Y(const Y&) {
cout << " Y(const Y&)n";
}
};
int main() {
Y obj1 = 2; // Line 1
}
输出:Y (int)
期望输出:Y(int)Y (const Y&)
Question>根据我的理解,第1行将首先创建一个临时对象Y(2),然后将临时对象赋值给obj1
。因此,我希望Y(int)
和Y(const Y&)
都被调用。但是vs2010的输出只报告第一个(即。Y(int)
)。为什么?
为什么?
因为在某些条件下(由c++ 11标准第12.8/31段指定),即使这些特殊函数(或析构函数)有副作用,也可以省略对复制构造函数或移动构造函数的调用:
拷贝/移动的省略在下列情况下允许进行称为复制省略的操作(可以合并为删除多个副本):
— [...]
-没有绑定到引用(12.2)的临时类对象将被复制/移动对于具有相同cv- undefined类型的类对象,可以通过将临时对象直接构造为省略的copy/move
的目标— [...]
这是所谓的"as-if"规则的唯一例外,该规则通常限制了编译器可以对程序执行的转换(优化)类型,以保持其可观察的行为。
注意,上面的机制被称为复制省略——即使它实际上是对被省略的move构造函数的调用。这是因为构造函数只有一个参数,而且没有标记为explicit
,所以编译器会自动转到:
Y obj1 = 2;
为:
Y obj1(2);
要防止此行为,请使用:
explicit Y(int ) {
cout << "Y(int)n";
}
这叫做 copy initialization
。Y(int )
是一个转换构造函数。这就是
未声明函数的单参数构造函数说明符明确
编译器被允许省略额外的副本并使用您的 conversion constructor
。这意味着
Y obj1 = 2; // Line 1
等价于
Y obj1(2); // Line 1
相关文章:
- 对复制 CTOR 和 CTOR 的未定义引用
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 将文件复制到自定义位置,存在字符串转换问题
- 为什么为派生类定义复制构造函数需要定义基类的默认构造函数?
- 为什么定义复制构造函数会给我错误:无法将类型 'obj&' 的非常量左值引用绑定到类型为"obj"的右值?
- 在C++中,我可以在定义自己的复制构造函数后跳过定义赋值运算符吗?
- 访问从联合与另一个成员集复制的联合中的一个成员是否未定义或未指定?
- emplace_back和push_back给出错误'double free or corruption (fasttop)'尽管定义了复制和移动构造函数
- C++11:没有复制构造函数的自定义基于范围的循环
- 创建用户定义的复制构造函数时无法创建对象
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 复制构造函数是始终隐式定义,还是仅在使用时定义?
- 用于 XML 的自定义 wxDataObject 格式,用于复制粘贴支持
- 自定义类对象的C++向量 - 复制构造函数已删除 - std::ifstream
- 复制构造函数C++中自定义类的动态数组
- 自定义类中的移动与复制性能
- 如何在自定义删除器的情况下复制unique_ptr
- 链表复制构造函数 |未定义的行为
- C++使用默认的复制构造函数,即使用户使用模板定义了一个复制构造函数
- 正在使用放置-new,复制存储,然后访问值未定义的行为