我有以下程序,我在析构函数中调用exit()。当我在main()中创建一个类型为sample的对象时,析构函数被调用一次并且程序正常退出。但是当我创建一个类型为sample的全局对象时,“Destructing ..”会被无限打印。有人可以解释一下吗?
#include "iostream"
#include "conio.h"
using namespace std;
class sample
{
public:
~sample() {
cout <<"Destructing.."<<endl;
exit(0);
}
};
sample obj;
int main()
{
getch();
}
答案 0 :(得分:2)
发生了什么,exit()
函数正在让程序在所有全局对象上调用析构函数。因为在你的类的析构函数调用exit(1);
时,对象尚未被认为是被破坏的,所以析构函数再次被调用,导致无限循环。
你可以逃脱这个:
class sample {
bool exiting;
public:
sample() { exiting = false; }
~sample() {
cout << "Destructing.." << endl;
if(exiting) return;
exiting = true;
exit(0);
}
};
但是有一个析构函数调用exit()
是一个坏主意。考虑其中一种选择:
main()
abort()
代替exit()
(感谢金发女郎提到这个)。 abort()
绕过通常在调用exit()
和main()
返回时执行的所有清理工作。然而,这也不一定是个好主意,因为程序中的某些清理操作可能非常关键。 abort()
仅适用于已经非常糟糕的错误,以至于需要绕过清理。之前我建议过例,但是记得从析构函数中抛出异常并改变了我的想法。 here's why.
另请注意,行为不一致 - 某些编译器/环境会导致无限循环,有些则不会。归结为在析构函数中的哪一点,对象被认为是被破坏的。我猜这个标准要么没有涵盖这一点,要么说这种情况下的行为是未定义的。
答案 1 :(得分:2)
我同意Micheal Slade的观点,即在析构函数中执行此操作是设计糟糕的标志。但如果您认为自己有充分理由(例如,开发问题),请使用abort()
代替exit(0)
。这样可以防止任何更多的析构函数被调用并让你退出递归循环。
答案 2 :(得分:1)
你的析构析构函数调用exit,而exit又调用destroy析构函数调用exit然后调用...(是的,它会持续很长时间)。