考虑以下情况:
struct X { ... };
struct Y
{
Y(...);
...
X x;
...
}
X f()
{
...
if (...)
throw E;
...
}
Y::Y(...) :
... ,
x(f()) ,
...
{
...
}
这里有未定义的行为吗?当抛出E时,这种设计是否存在任何问题或潜在问题?
更新
Y::x
可能不是Y
的唯一成员变量,可能不是类中的第一个成员变量,可能会在Y::Y
初始化列表的一半初始化。< / p>
答案 0 :(得分:5)
这里有未定义的行为吗?
没有。 Y
的构造已中止。
当抛出E时,这种设计是否存在任何问题或潜在问题?
永远不会创建Y
,因此没有析构函数可以调用。完全构造的元素的析构函数,即在类体中x
之前声明的元素,将被自动调用(否则你怎么知道它抛出时的初始化列表有多远)。如果你需要销毁任何东西,那么你必须抓住异常并自行销毁它。你不能吸收异常,你可以重新抛出它,抛出一个新的异常,或者什么都不做会导致异常被重新抛出。对于您的特定用例,不应该有任何可以破坏的内容,因为根本不会调用构造函数体。
答案 1 :(得分:2)
当在构造对象期间抛出异常时,将调用所有完全构造的子对象的析构函数。也就是说,假设您的类型X
正确地抛出异常,清除它在抛出异常之前可能已分配的任何资源,则没有问题。