fre*_*low 17
如果在构造期间抛出异常,则将正确销毁所有先前构造的子对象.以下程序证明基础肯定被破坏:
struct Base
{
~Base()
{
std::cout << "destroying base\n";
}
};
struct Derived : Base
{
Derived()
{
std::cout << "throwing in derived constructor\n";
throw "ooops...";
}
};
int main()
{
try
{
Derived x;
}
catch (...)
{
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
throwing in derived constructor
destroying base
Run Code Online (Sandbox Code Playgroud)
(请注意,本机指针的析构函数不执行任何操作,这就是为什么我们更喜欢RAII而不是原始指针.)
是.规则是构造函数成功完成的每个对象都将在异常时被破坏.例如:
class A {
public:
~A() {}
};
class B : public A {
public:
B() { throw 0; }
~B() {}
};
Run Code Online (Sandbox Code Playgroud)
调用~A().〜B()未被调用;
编辑:此外,假设你有成员:
struct A {
A(bool t) { if(t) throw 0; }
~A() {}
};
struct B {
A x, y, z;
B() : x(false), y(true), z(false) {}
};
Run Code Online (Sandbox Code Playgroud)
会发生什么:x被构造,y被抛出,x被破坏(但是y和z都没有).
抛出异常时,将为其构造函数成功运行的所有(子)对象调用析构函数.这扩展到数据成员和基类.
例如,对于此代码
struct base {};
struct good {};
struct bad {
bad() {throw "frxgl!";}
};
struct test : public base {
std::string s;
good g;
bad b;
test() {}
};
Run Code Online (Sandbox Code Playgroud)
之前test被执行的构造,第一基类的构造函数被调用,则该构造函数s,g和b.只有这些成功完成,test才会执行构造函数.当异常的建设过程中引发的b,基类的构造函数以及构造函数的数据成员s和g已全面执行,因此,它们的析构函数运行.test它本身的构造函数并b没有成功运行,因此它们的析构函数不会运行.