在写这篇文章之前,一直没有注意过C++中临时对象何时调用析构的。直到最近看代码的过程中遇到这种情况。
由于不了解临时对象何时调用析构函数,所以很不了解代码的实现。甚至还用局部对象的析构时机去看待。先讲讲自己遇到的情况:博主是在看mudo日志库时候遇到的,在mudo日志库中类Logger的析构函数回去获取输入的Buffer,并写入到文件或标准输出。实现在需要打印日志的地方会创建临时对象Logger,由于在该临时对象析构时才会输出。因此,理解何时调用就至关重要了。
首先,我们先看看局部对象的构造和析构的调用时机。
#include <iostream>
#include <string>
using namespace std;
class CPartObj
{
public:
CPartObj(string strInfo)
:m_strInfo(strInfo)
{
cout << "CPartObj" << m_strInfo << endl;
}
~CPartObj()
{
cout << "~CPartObj" << m_strInfo << endl;
}
private:
string m_strInfo;
};
void Function(void)
{
CPartObj Obj1("Obj1");
CPartObj Obj2("Obj2");
CPartObj Obj3("Obj3");
}
int main(void)
{
Function();
return 0;
}
运行结果如下所示:
CPartObjObj1
CPartObjObj2
CPartObjObj3
~CPartObjObj3
~CPartObjObj2
~CPartObjObj1
从测试结果我们可以看出局部对象的构造和析构时机:在定义的时候调用构造,在离开局部作用域后调用析构,多个对象的析构顺序先构造的后析构,后构造的先析构。
接下来我们看看临时对象的构造和析构时机,同样的我们先看个例子:
#include <iostream>
#include <string>
using namespace std;
class CTmpObj
{
public:
CTmpObj()
{
cout << "CTmpObj" << endl;
}
~CTmpObj()
{
cout << "~CTmpObj" << endl;
}
};
int main(void)
{
CTmpObj(); //临时对象
system("pause");
return 0;
}
运行后果如下所示:
CTmpObj
~CTmpObj
请按任意键继续. . .
注意到和局部对象不同的是,在未离开作用域时候已经调用析构了,我们进行单步调试,在执行完临时对象这条语句之后,就调用析构函数了。
为此,是不是临时对象的析构是在创建了该临时对象的语句结束后调用的呢?
我们在看接下来的另一个例子:
#include <iostream>
#include <string>
using namespace std;
class CTmpObj
{
public:
CTmpObj()
{
cout << "CTmpObj" << endl;
}
~CTmpObj()
{
cout << "~CTmpObj" << endl;
}
};
int main(void)
{
CTmpObj(), //逗号运算符,这里并不是语句的结束
cout << "statement mid" << endl, //逗号运算符,这里并不是语句的结束
cout << "statement end" << endl; //这里才是语句的结束
cout << "other statement" << endl; //另一条语句
system("pause");
return 0;
}
下面是运行的结果:
CTmpObj
statement mid
statement end
~CTmpObj
other statement
请按任意键继续. . .
从上面的运行结果可以验证我们的猜测。
我们可以得出:临时对象的构造函数在生成该临时对象的时候调用,在执行完创建该临时对象的语句之后就析构掉了,也就是遇到了分号。
原文地址:https://blog.youkuaiyun.com/huangjh2017/article/details/70243033