没有调用复制构造函数?

时间:2013-05-30 19:15:49

标签: c++ class memory dynamic constructor

据我所知,在以下情况下你会调用复制构造函数:
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;
}

2 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:3)

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

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

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

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