构造函数中的异常
Exceptions in constructors
考虑以下 class:
struct A
{
A(){ std::cout << "A()" << std::endl; throw std::exception(); }
~A(){ std::cout << "~A()" << std::endl; }
};
A a;
int main(){ }
标准承诺将调用适当的释放函数N4296::5.3.4/20 [expr.new]
:
If any part of the object initialization described above78 terminates
by throwing an exception, storage has been obtained for the object,
and a suitable deallocation function can be found, the deallocation
function is called to free the memory in which the object was being
constructed,
但是析构函数呢?在那个例子中,它没有被调用。那么,我们得到 UB 了吗?
为所有成功初始化的对象调用析构函数。
否则必须进行默认的零初始化(一些开销)才能在析构函数中承担任何事情。
构造函数抛出异常的 A 对象未成功初始化。所以它的析构函数没有被执行。但是,如果它有任何class类型的子对象(基础class子对象,数据成员)在异常之前已经成功初始化,那么将为这些调用析构函数。
不,从构造函数中抛出不是 UB。
相反,它是发出构造失败信号的常见方式,它确保调用者要么有一个成功初始化且可能可用的对象,要么(只是)一个异常。
历史。最初 C++ 没有例外。然后通过将 0 分配给 this
来表示构造失败。我不记得它是如何与分配交互的,但大概与异常现在的交互方式相同,即有保证的释放。但是使用这个方案你只能失败动态分配对象的构造......
析构函数与释放函数不同。每当变量超出范围时,引用该变量的对象将被删除。题中你给的对象是一个全局变量,所以程序结束时会被删除
考虑以下 class:
struct A
{
A(){ std::cout << "A()" << std::endl; throw std::exception(); }
~A(){ std::cout << "~A()" << std::endl; }
};
A a;
int main(){ }
标准承诺将调用适当的释放函数N4296::5.3.4/20 [expr.new]
:
If any part of the object initialization described above78 terminates by throwing an exception, storage has been obtained for the object, and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed,
但是析构函数呢?在那个例子中,它没有被调用。那么,我们得到 UB 了吗?
为所有成功初始化的对象调用析构函数。
否则必须进行默认的零初始化(一些开销)才能在析构函数中承担任何事情。
构造函数抛出异常的 A 对象未成功初始化。所以它的析构函数没有被执行。但是,如果它有任何class类型的子对象(基础class子对象,数据成员)在异常之前已经成功初始化,那么将为这些调用析构函数。
不,从构造函数中抛出不是 UB。
相反,它是发出构造失败信号的常见方式,它确保调用者要么有一个成功初始化且可能可用的对象,要么(只是)一个异常。
历史。最初 C++ 没有例外。然后通过将 0 分配给 this
来表示构造失败。我不记得它是如何与分配交互的,但大概与异常现在的交互方式相同,即有保证的释放。但是使用这个方案你只能失败动态分配对象的构造......
析构函数与释放函数不同。每当变量超出范围时,引用该变量的对象将被删除。题中你给的对象是一个全局变量,所以程序结束时会被删除