2013-05-30 56 views
1

据我所知在下列情况下调用复制构造函数:
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; 
} 
+4

你没有错。它只是优化了。 – jrok

+1

哇。我花了几个小时思考这个问题。至少我现在不会忘记它! – Bloodcount

+1

@Bloodcount重要的是你学会了它,不会忘记它。如果你问我,这些花费几个小时。 –

回答

3

在几乎所有情况下,编译器是不允许改变的意义你的代码它可以(也可以在优化时)将你的代码从你写的东西中大幅改变为更优化的东西,而不会改变你的可观察行为代码。

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

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

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