C ++:如果抛出异常,超出范围的对象是否被销毁?

时间:2015-02-18 16:30:42

标签: c++ exception visual-studio-2008 scope throw

通常它会在范围结束时被破坏..我可以看到如果抛出异常就会出现问题。

3 个答案:

答案 0 :(得分:6)

C ++标准版n3337

15异常处理

§ 15.2构造函数和析构函数

  

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

     

2)任何存储持续时间的对象,其初始化或   如果异常将具有析构函数,则终止销毁   执行所有完全构建的子对象(不包括   类似联合类的变体成员),即子对象的变体成员   主要构造函数(12.6.2)已完成执行和   析构函数尚未开始执行。同样,如果   对象的非委托构造函数已完成执行并且a   委托该对象的构造函数以异常退出   将调用object的析构函数。如果对象是在一个中分配的   new-expression,匹配解除分配函数(3.7.4.2,5.3.4,   12.5),如果有的话,被调用来释放对象占用的存储空间。

     

3)为自动对象调用析构函数的过程   构造在从try块到throw-expression的路径上   称为“堆栈展开。”如果在堆栈期间调用析构函数   unwinding以异常退出,调用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
}

答案 1 :(得分:1)

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

void work()
{
     Foo a;
     Foo* b = new Foo;
     // ... later

     // exception thrown

     delete b;
}

在这个示例中,当堆栈展开时抛出异常时会调用a的析构函数,但b指向的内存将被泄露,因为它永远不会到达delete致电。这是RAII如此有用的众多原因之一。

答案 2 :(得分:0)

是。当您离开范围(无论是正常还是异常)时,该范围的本地对象将被销毁。这是使RAII / SBRM发挥作用的基本事实。