为什么不调用复制构造函数将临时对象复制到新定义的对象

Why Copy constructor is NOT called to copy the temporary object to the new defined object

本文关键字:复制 定义 对象 构造函数 调用 临时对象 为什么不 新定义      更新时间:2023-10-16
#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