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

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

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

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

是的,任何作用域绑定变量都将被销毁。

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

     // exception thrown

     delete b;
}

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

是的。

C++ 标准 n3337

15个异常处理

§ 15.2 构造函数和析构函数

1) As control passes from a throw-expression to a handler, destructors are invoked for all automatic objects constructed since the try block was entered. The automatic objects are destroyed in the reverse order of the completion of their construction.

2) An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.

3) The process of calling destructors for automatic objects constructed on the path from a try block to a throw-expression is called “stack unwinding.” If a destructor called during stack unwinding exits with an exception, std::terminate is called (15.5.1). [ Note: So destructors should generally catch exceptions and not let them propagate out of the destructor. — end note ]

示例:

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