4

我有以下程序,我在析构函数中调用 exit() 。当我在 main() 内创建一个 sample 类型的对象时,析构函数被调用一次并且程序正常退出。但是当我创建一个样本类型的全局对象时,“Destructing..”会被无限打印出来。谁能解释一下如何?

#include "iostream"
#include "conio.h"

using namespace std;

class sample
{
      public:
     ~sample() {
                    cout <<"Destructing.."<<endl;
                    exit(0);
                }
};

sample obj;

int main()
{
 getch();   
}
4

3 回答 3

2

我同意 Micheal Slade 的观点,即在析构函数中这样做是糟糕设计的标志。但是,如果您认为有充分的理由这样做(例如,开发问题),请abort()使用exit(0). 这将防止调用更多的析构函数并使您退出递归循环。

于 2012-04-30T06:10:20.407 回答
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()

我之前建议过异常,但记得从析构函数内部抛出异常并改变了主意。这就是为什么。

另请注意,行为并不一致 - 一些编译器/环境会导致无限循环,而有些则不会。它归结为在析构函数中的哪个点对象被认为被销毁。我猜这个标准要么没有涵盖这一点,要么说这种情况下的行为是未定义的。

于 2012-04-30T06:07:27.300 回答
1

您的破坏性析构函数调用 exit 进而调用破坏析构函数,该析构函数调用 exit 又调用 ... (是的,它持续了很长时间)。

于 2012-04-30T06:03:19.617 回答