写看如下代码:
#include <iostream>
using namespace std;
class B
{
public:
B()
{
cout << "default constructor" << " ";
}
B(int i) : data(i)
{
cout << "constructed by parameter" << data << " ";
}
~B()
{
cout << "destructed" << " ";
}
private:
int data;
};
B Play(B b)
{
return b;
}
int main()
{
B temp = Play(5);
return 0;
}
程序运行结果:
一开始,我对这个结果有点不相信。我一开始对这段代码的分析如下:
Play(5)
函数先调用带参数的构造函数构造一个局部的对象b,然后Play
函数返回b对象,这个时候会调用拷贝构造函数用局部对象b构造一个临时对象,然后局部对象b调用析构函数。接下来调用拷贝构造函数用临时对象构造一个对象temp,然后临时对象调用析构函数,最后程序结束之前temp调用析构函数。
根据上面分析,在屏幕的打印结果应该如下:
constructed by parameter5 destructed destructed destructed destructed
和实际的打印结果有出入,这是为什么呢?
经过研究,我终于发现了问题所在。在B temp = Play(5);
中,Play函数返回一个临时对象,然后直接把这个临时对象当做temp对象了,也算是一种优化吧。所以临时对象(temp)在main函数结束之前才调用析构函数。
再看如下代码:
#include <iostream>
using namespace std;
class B
{
public:
B()
{
cout << "default constructor" << " ";
}
B(int i) : data(i)
{
cout << "constructed by parameter" << data << " ";
}
~B()
{
cout << "destructed" << " ";
}
private:
int data;
};
B Play(B b)
{
return move(b);
}
int main()
{
Play(5);
return 0;
}
程序运行结果:
我们可以看到,当调试时,在Play函数执行完以后临时变量就已经调用析构函数了。也就是说在没有用一个初始化的对象来接收返回的对象时,当所调的函数执行完毕之后,临时对象就调用析构函数并且被销毁了。