MST

星途 面试题库

面试题:C++中在异常处理时析构函数的调用机制

当C++程序发生异常时,涉及到多个对象的情况下,析构函数是如何被调用的?请结合栈展开(stack unwinding)机制进行说明,并举例代码演示。
43.0万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 栈展开机制下析构函数调用原理

当C++程序发生异常时,栈展开机制会从异常抛出点开始,按顺序回退栈帧,销毁在异常发生前创建的局部对象。每个局部对象在其作用域结束时,会调用其析构函数。这种机制确保了资源的正确释放,防止内存泄漏等问题。

2. 示例代码

#include <iostream>

class A {
public:
    A() { std::cout << "A constructor" << std::endl; }
    ~A() { std::cout << "A destructor" << std::endl; }
};

class B {
public:
    B() { std::cout << "B constructor" << std::endl; }
    ~B() { std::cout << "B destructor" << std::endl; }
};

class C {
public:
    C() { std::cout << "C constructor" << std::endl; }
    ~C() { std::cout << "C destructor" << std::endl; }
};

void func() {
    A a;
    B b;
    C c;
    throw 1;
}

int main() {
    try {
        func();
    } catch (int) {
        std::cout << "Caught exception" << std::endl;
    }
    return 0;
}

3. 代码分析

在上述代码中,func函数创建了三个对象abc。当throw 1;语句抛出异常时,栈展开机制开始工作。

  • 首先,c对象的析构函数被调用,因为它是在栈顶最近创建的对象,输出C destructor
  • 接着,b对象的析构函数被调用,输出B destructor
  • 最后,a对象的析构函数被调用,输出A destructor
  • 然后catch块捕获到异常,输出Caught exception

这样通过栈展开机制,在异常发生时,局部对象会按照其创建的相反顺序调用析构函数,确保资源的正确释放。