85

在 C++ 中,如果构造函数抛出异常,会运行哪些析构函数?

特别是,如果异常发生在初始化列表或正文期间,会有什么不同吗?

另外,继承和成员呢?大概所有已完成的建筑都会被摧毁。如果只构造了一些成员,那么只有那些成员会被破坏吗?如果存在多重继承,是否所有已完成的构造函数都会被破坏?虚拟继承会改变什么吗?

4

3 回答 3

79

如果构造函数抛出异常,会运行哪些析构函数?

在该范围内完全创建的所有对象的析构函数。

如果异常发生在初始化列表或正文期间,有什么区别吗?

所有已完成的对象都将被销毁。
如果构造函数从未被完全调用过,则对象从未被构造,因此不能被破坏。

继承和成员呢?大概所有已完成的建筑都会被摧毁。如果只构造了一些成员,那么只有那些成员会被破坏吗?如果存在多重继承,是否所有已完成的构造函数都会被破坏?虚拟继承会改变什么吗?

所有已完成的建筑都会遭到破坏。是的,只有完全创建的对象才会被破坏。

好读:

Herb Sutter 的构造函数失败

特别是,喜欢他解释的部分:

用生物学术语来说,受孕发生了——构造函数开始了——但是尽管尽了最大的努力,还是流产了——构造函数从未跑到term(ination)。

顺便说一句,这就是为什么如果构造函数没有成功就永远不会调用析构函数的原因——没有什么可以销毁的。“它不会死,因为它从未活过。” 请注意,这使得短语“构造函数引发异常的对象”实际上是矛盾的。这样的东西甚至比以前的对象还要少……它从未存在过,从未存在过,从未呼吸过它的第一次呼吸。

于 2012-04-18T15:35:15.087 回答
23

在 C++ 中,如果构造函数抛出异常,会运行哪些析构函数?

所有具有构造函数的对象都运行完成。

特别是,如果异常发生在初始化列表或正文期间,会有什么不同吗?

不会。在异常之前完全构造的所有成员都将运行其析构函数。在构造过程中抛出的成员和所有其他非构造成员将不会运行其析构函数。成员构造的顺序是明确定义的,因此如果您知道异常抛出的点,您就可以确切地知道会发生什么。

另外,继承和成员呢?

同样的规则适用。

大概所有已完成的建筑都会被摧毁。

是的

如果只构造了一些成员,那么只有那些成员会被破坏吗?

是的

如果存在多重继承,是否所有已完成的构造函数都会被破坏?

是的

虚拟继承会改变什么吗?


,但请注意:虚拟继承确实会影响调用构造函数的顺序。如果您不熟悉订单是如何定义的,那么在您查找确切的规则之前,这可能是不直观的。

于 2012-04-18T16:48:27.073 回答
6

由于构造函数而在本地范围内创建的任何对象都将被破坏。运行时处理返回堆栈,调用析构函数,直到找到处理程序。

如果从构造函数中抛出异常,则将调用所有完全构造的子对象的析构函数。此外,如果构造函数是new表达式的一部分,则将调用适当的放置删除运算符(如果存在)。

于 2012-04-18T15:43:29.497 回答