C++:如果抛出异常,那么超出范围的对象将被销毁

C++: If an exception is thrown, are objects that go out of scope destroyed?

本文关键字:对象 范围 如果 抛出异常 C++      更新时间:2023-10-16

通常情况下,它会在作用域结束时被销毁。。不过,如果抛出异常,我可以看到问题的发生。

是。

C++标准n3337

15异常处理

§15.2构造函数和析构函数

1) 当控件从抛出表达式传递到处理程序时,析构函数为自try块以来构造的所有自动对象调用已输入。自动对象按相反的顺序销毁他们的建设完成。

2) 任何存储持续时间的对象,其初始化或由异常终止的销毁将具有销毁函数为完全构造的子对象的所有执行(不包括类并集的变体成员),即用于的子对象主建造师(12.6.2)已完成执行,以及析构函数尚未开始执行。类似地,如果对象的非委托构造函数已完成执行该对象的委托构造函数退出时出现异常将调用对象的析构函数。如果对象是在新的表达式,匹配的解除分配函数(3.7.4.2、5.3.4,12.5)(如果有的话)被调用以释放该对象所占用的存储器。

3) 为自动对象调用析构函数的过程在从try块到throw表达式的路径上构造的是称为"堆栈展开"。如果在堆栈期间调用了析构函数展开退出时出现异常,调用std::terminate(15.5.1)。[注意:所以析构函数通常应该捕获异常,而不是让它们从析构函数中传播出来。——尾注]

示例:

SomeClass c;              // declared before try{} so it is
                          // still valid in catch{} block
try {
    SomeClass t;
    throw;
} catch( ...) {
    // t destroyed
    // c valid
}

是的,任何范围绑定变量都将被销毁。

void work()
{
     Foo a;
     Foo* b = new Foo;
     // ... later
     // exception thrown
     delete b;
}

在本例中,当堆栈展开时抛出异常时,会调用a的析构函数,但b指向的内存会泄漏,因为它永远无法到达delete调用。这是RAII如此有帮助的众多原因之一。

是。当您离开一个作用域(无论是正常情况下还是通过异常情况)时,该作用域的本地对象将被销毁。这是RAII/SBRM发挥作用的基本事实。