1

可能重复:
为什么在这种情况下不调用复制构造函数?

我有以下代码:

#include <iostream>
#include <new>

using namespace std;

class test {  
    int *p;  
public:
    test operator=(test a);
    test()  {
        p = new int [2];
        cout <<"Default Constructor was done here." << "\n";
    }

    test(const test &a) {
        p = new int [2];
        this->p[0] = a.p[0];
        this->p[1] = a.p[1];
        cout << "Copy Constructor was done here." << "\n";
    }

    ~test() {
        delete p;
        cout << "Destructor was done here." << "\n";
    }
    int set (int a, int b) {
        p[0] = a;
        p[1] = b;
        return 1;
    }

    int show () {
        cout << p[0] << " " << p[1] << "\n";
        return 2;
    }
};    

test test::operator=(test a) {
    p[0] = a.p[0]; 
    p[1] = a.p[1]; 
    cout << "Operator = was done here" << "\n";
    return *this;
}

test f(test x) {
    x.set(100, 100);
    return x;
}

int main () {
    test first;
    test second;
    first.set(12, 12);

    //f(first);
    //second = first;
    second = f(first);


    first.show();
    second.show();

    getchar ();
    return 0;
}

Copy Constructor 只被调用了 3 次?为什么?如果我理解的话,我们做了四个副本(我们将对象发送到 func,func 返回值,我们将对象发送到 operator=,operator= 返回值)。

4

1 回答 1

3

这很可能是复制省略的影响。编译器可以自由地避免在不影响程序的任何地方复制对象。在这种情况下,复制构造函数/析构函数的副作用不被视为对程序的影响。一般来说,它会避免复制一个临时值以用作函数参数,因为无论如何这个临时值都会在之后被销毁。

这可以在标准的 §12.8.32 中找到:

当满足某些条件时,允许实现省略类对象的复制/移动构造,即使对象的复制/移动构造函数和/或析构函数具有副作用。在这种情况下,实现将省略的复制/移动操作的源和目标简单地视为引用同一对象的两种不同方式,并且该对象的销毁发生在两个对象本应被删除的较晚时间。没有优化就被破坏了。这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的(可能结合起来消除多个副本):


  • 在具有类返回类型的函数的返回语句中,当表达式是具有与函数返回类型相同的 cv 非限定类型的非易失性自动对象的名称时,
    可以通过构造自动
    对象直接转化为函数的返回值
  • 在 throw 表达式中,当操作数是非易失性自动对象的名称时,其范围不超出最内层封闭 try 块(如果有)的末尾,则从操作数复制/移动操作到可以通过将自动对象直接构造到异常对象中来省略异常对象(15.1)
  • 当尚未绑定到引用 (12.2) 的临时类对象将被复制/移动到具有相同 cv 非限定类型的类对象时,可以通过将临时对象直接构造到目标中来省略复制/移动操作省略的
    复制/移动
  • 当异常处理程序的异常声明(第 15 条)声明与异常对象(15.1)具有相同类型的对象(cv 限定除外)时,可以通过将 异常声明视为别名
    来省略复制/移动操作
    对于异常
    对象,如果程序的含义将保持不变,除非为
    异常声明声明的对象执行构造函数和析构函数。

在这种情况下,它可能会简单地使用返回的对象f作为 的输入operator=,因为它是临时的,因此无论如何都会在之后被销毁。

于 2012-06-29T13:07:55.210 回答