没有调用复制构造函数?

Posted

技术标签:

【中文标题】没有调用复制构造函数?【英文标题】:Copy constructor not called? 【发布时间】:2013-05-26 11:59:58 【问题描述】:

据我所知,您在以下情况下调用复制构造函数: 1 当实例化一个对象并用另一个对象的值初始化它时 2 当按值传递对象时。 3 当对象按值从函数返回时。 我决定对此进行测试,并制作了这个小程序来测试它(每次调用构造函数时都会发送消息。它似乎适用于前两种情况,但不适用于第三种情况。我想找出我的错误. 欢迎提出想法。

#include <iostream>

using namespace std;

class Circle
private:
    double* data;
public:
    Circle();
    Circle(double* set);
    Circle(const Circle& tt1);
    ~Circle();
    Circle& operator=(const Circle& tt1);
;



Circle :: Circle()

    cout << "Default constructor called" << endl;
    data = NULL;


Circle :: Circle(double* set)

    cout << "Set up constructor called" << endl;
    data = new double[3];
    copy(set, set+3, data);


Circle :: Circle(const Circle& tt1)

    cout << "Copy constructor called" << endl;
    data = new double[3];
    copy(tt1.data, tt1.data+3, this->data);

Circle :: ~Circle()

    cout << "Destructor called!" << endl;
    delete[] data;


Circle& Circle :: operator=(const Circle& tt1)

    cout << "Overloaded = called" << endl;
    if(this != &tt1)
    
        delete[] this->data;
        this->data  = new double[3];
        copy(tt1.data, tt1.data+3, this->data);
    
    return *this;


void test2(Circle a)



Circle test3()

    double arr [] =  3, 5, 8, 2;
    Circle asd(arr);
    cout<< "end of test 3 function" << endl;
    return asd;


int main()

    cout <<"-------------Test for initialization" << endl;
    double arr [] =  16, 2, 7;
   Circle z(arr);
    Circle y = z;
   cout << "-------------Test for pass by value" << endl;
   test2(z);
   cout <<"------------- Test for return value-------"<<endl;
   Circle work = test3();

    cout<< "-----------Relese allocated data" << endl;
    return 0;

【问题讨论】:

你没看错。它只是被优化掉了。 哇。我确实花了几个小时思考这个问题。好吧,至少我现在不会忘记它! @Bloodcount 重要的是你学会了它并且不会忘记它。如果你问我,那几个小时是值得的。 【参考方案1】:

由于Return Value Optimization,第三个测试用例的复制构造函数调用被编译器优化掉了。

【讨论】:

谢谢!注意到和学习!【参考方案2】:

几乎在所有情况下,编译器都不允许更改代码的含义。它可以(并且会在优化时)将您的代码从您编写的内容大幅更改为更优化的内容,同时永远不会改变您的代码的可观察行为。

这就是为什么在调试时您会看到许多令人困惑的事情,因为生成的代码与您编写的代码完全不同,同时保持可观察状态不变。这实际上使编写调试器变得困难 - 例如,如果您想在调试时检查变量的值,编译器可能已经决定该变量甚至不需要存在,所以在这种情况下调试器应该显示什么?

在极少数情况下,允许编译器更改代码的含义。 RVO 和 NRVO [与上述相同的链接] 是其中的两个示例 - 在这些有限的情况下允许编译器省略复制构造函数 - 这就是您所看到的。编译器仍应检查您的复制构造函数是否存在且可访问 - 例如,它不是私有的、已删除的或无法生成 - 但它不能使用它。

出于这个原因,复制构造函数 [和推理析构函数] 应该只是做正常的事情 - 就好像它们被忽略了,你会得到明显不同的行为。

【讨论】:

以上是关于没有调用复制构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

c++,类的对象作为形参时一定会调用复制构造函数吗?

C++中复制构造函数被调用的三种情况

对象 && 复制构造函数

对象做函数参数和函数返回值时,调用复制构造函数,构造函数,析构函数的情况

复制构造函数中的c ++用户定义成员

复制构造函数的运用