1️⃣ destructor 函数的调用时机

  • 对象正常状态下被销毁,也就是当它离开了它的作用域(scope)或是被明确地删除。
  • 当对象被exception处理机制销毁——也就是exception传播过程中的(stack-unwinding)机制。

2️⃣ 理由一

  • 有个exception正撰写你的destructor。因为如果控制权基于exception的因素离开destructor,而此时正有另一个exception处于作用状态,C++会调用terminate函数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Session
    {
    public:
    Session();
    ~Session();
    ...
    private:
    static void logCreation(Session* objAddr);
    static void logDestruction(Session* objAddr);
    };
  • 函数 logCreationlogDestruction 分别用来记录对象的构造和析构。

    1
    2
    3
    4
    Session::~Session()
    {
    logDestruction(this);
    }
    • 如果 logDestruction抛出一个异常 exception,会发生什么事情?
      • 首先,这个exception并不会被Session::destructor捕捉,所以它会传播到destructor的调用端。
      • 其次,万一这个destructor本身是因其他某个exception而被调用的,terminate函数便会被自动调用,于是程序会直接走上了黄泉路。

3️⃣ 理由二

  • 如果exceptiondestructor 内抛出,而且没有在本地被捕捉到,那么就destructor执行不完全。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Session::Session()				// 为了简化,这个ctor不处理exceptions。
    {
    logCreation(this);
    startTransaction(); // 开始一个数据库事务。
    }

    Session::~Session()
    {
    logDestruction(this);
    endTransaction(); //结束一个数据库事务。
    }
  • 如果logDestruction抛出一个exception,于Session::Session内创建的那个Transaction绝对不会结束。

  • 或许在本例中,我们可以调换destructor中语句的位置,但是如果endTransaction抛出异常,同样 destructor中不会执行完整。