代码之家  ›  专栏  ›  技术社区  ›  mczarnek

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

  •  8
  • mczarnek  · 技术社区  · 11 年前

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

    3 回复  |  直到 11 年前
        1
  •  13
  •   4pie0    11 年前

    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
    }
    
        2
  •  3
  •   Cory Kramer    11 年前

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

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

    在此示例中 a 当堆栈展开时引发异常时,将调用的析构函数,但 b 因为它永远不会到达 delete 呼叫这是RAII如此有用的众多原因之一。

        3
  •  1
  •   Jerry Coffin    11 年前

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

    推荐文章