构造函数是一个特殊的成员函数,当创建对象时编译器会自动调用它,而析构函数也是一个特殊的成员函数,当对象超出范围时,编译器也会隐式调用它。当动态分配的对象被分配和销毁时,它们也被调用,new运算符分配存储并调用构造函数,delete运算符调用析构函数并释放new分配的内存。
是否可以显式调用构造函数和析构函数?
是的,程序员可以显式调用特殊的成员函数。以下程序显式调用构造函数和析构函数。
#include
using namespace std;
class Test
{
public:
Test() { cout << "Constructor is executed\n"; }
~Test() { cout << "Destructor is executed\n"; }
};
int main()
{
Test(); // Explicit call to constructor
Test t; // local object
t.~Test(); // Explicit call to destructor
return 0;
}
输出:
Constructor is executed
Destructor is executed
Constructor is executed
Destructor is executed
Destructor is executed
当显式调用构造函数时,编译器将创建一个无名的临时对象,并立即将其销毁。这就是为什么输出中的第二行是对析构函数的调用。
这是我和Bjarne Stroustrup博士之间通过邮件就此主题进行的对话:
我:为什么C++允许显式调用构造函数?您不认为这不应该吗?
Bjarne博士:否。类类型的临时对象很有用。
C++标准的第12.4 / 14节指出:
一旦为一个对象调用了析构函数,该对象就不复存在了。如果为生存期已结束的对象调用析构函数,则该行为未定义。[示例:如果显式调用了自动对象的析构函数,并且随后以通常会调用对象的隐式销毁的方式保留该块,行为是不确定的。 —结束示例]。
如此处所述,我们永远不要在本地(自动)对象上显式调用析构函数,因为这样做确实会导致不良结果。
当本地对象超出范围时,它们将被编译器自动销毁,这是C++语言的保证。通常,不应显式调用特殊成员函数。
构造函数和析构函数也可以从类的成员函数中调用。请参阅以下程序:
#include
using namespace std;
class Test
{
public:
Test() { cout << "Constructor is executed\n"; }
~Test() { cout << "Destructor is executed\n"; }
void show() { Test(); this->Test::~Test(); }
};
int main()
{
Test t;
t.show();
return 0;
}
输出:
Constructor is executed
Constructor is executed
Destructor is executed
Destructor is executed
Destructor is executed
仅当通过使用new放置将对象放置在内存中的特定位置时,才需要显式调用析构函数。动态分配对象时,不应显式调用析构函数,因为delete运算符自动调用析构函数。
作为练习,请预测以下程序的输出:
#include
using namespace std;
class Test
{
public:
Test() { cout << "Constructor is executed\n"; }
~Test() { cout << "Destructor is executed\n"; }
friend void fun(Test t);
};
void fun(Test t)
{
Test();
t.~Test();
}
int main()
{
Test();
Test t;
fun(t);
return 0;
}
资料来源:
http://www.parashift.com/c++-faq/dont-call-dtor-on-local.html
http://www.parashift.com/c++-faq/placement-new.html
http://msdn.microsoft.com/en-us/library/35xa3368.aspx