class human
{
public:
human()
{
cout << "construct " << endl;
human_num++;
}
static int human_num;
~human()
{
human_num--;
cout << "delete " << this << " ";
print();
}
void print()
{
cout << "human num is : " << human_num << endl;
}
human(const human& b)
{
cout << "copy construct" << endl;
human_num++;
}
};
int human::human_num = 0;
human f1(human x)
{
cout << "x.print ";
x.print();
return x; //返回不创建临时对象,只调用复制构造函数初始化h2//涉及RVO和NRVO优化
}
int main()
{
human h1;
h1.print();
human h2 = f1(h1);
h2.print();
return 0;
}
程序输出:3次构建对象,3次析构对象
construct //构建h1
human num is : 1
copy construct //按值传递参数,调用复制构造函数 构建形参x
x.print human num is : 2
copy construct //return x调用复制构造函数 构建并初始化h2
delete 010FFC54 human num is : 2 //析构局部变量x ,对x跟踪地址是010FFC54
human num is : 2 //h2.print();
delete 010FFD4B human num is : 1 //析构h2 h2跟踪地址为010FFD4B
delete 010FFD57 human num is : 0 //析构h1 h1跟踪地址为010FFD57
分析:
前几行基本分析都在上述程序输出中指明,
最后两行是h2和h1的析构
注意 这里要重点强调的是return x为什么没有创建临时对象,不同于普通的赋值,这里是初始化一个对象就不创建临时对象。
具体原因涉及编译器优化(RVO和NRVO)。 RVO (return value optimization) 和NRVO (named return value optimization) 是C++在处理 “返回一个class object的函数”时常用的优化技术,主要作用就是消除临时对象的构造和析构成本。
gcc中有一个-fno-elide-constructors的命令,可以去掉任何返回值优化。
如果这样写:
human h2;
h2 = f1(h1);
这将创建一个临时对象用于赋值给h2,除了析构局部变量x,也将析构该临时对象
最终输出如下:4次构建对象,4次析构对象,比上面例子的函数返回值用来初始化对象少一次构建析构
construct
human num is : 1
construct
copy construct //构建x
x.print human num is : 3
copy construct //return创建一个临时对象存储返回结果
delete 006FF854 human num is : 3 //函数调用结束,析构x,因为此时临时对象还有用
delete 006FF880 human num is : 2 //析构return产生的临时对象
human num is : 2
delete 006FF958 human num is : 1
delete 006FF964 human num is : 0