【问题标题】:What destructors are run when the constructor throws an exception?当构造函数抛出异常时会运行哪些析构函数?
【发布时间】:2012-04-30 01:38:22
【问题描述】:

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

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

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

【问题讨论】:

  • 有什么原因你没有自己测试这个吗?
  • @Steve:因为如果您想要可移植或可维护的代码,那么依赖一个特定编译器版本的行为是一个糟糕的主意。
  • @BenVoigt - 我在理论上同意。但是当你在现实世界中编码时,你必须处理现实。如果所有主要编译器都没有做到这一点,我会感到非常惊讶。

标签: c++ constructor exception-handling destructor


【解决方案1】:

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

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

异常是在初始化列表还是正文期间有什么区别吗?

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

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

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

好读:

Constructor Failures by Herb Sutter

特别喜欢他解释的部分:

在生物学术语中,受孕发生了——构造函数开始了——但尽管尽了最大的努力,随后还是流产了——构造函数从未运行到终止(终止)。

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

【讨论】:

【解决方案2】:

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

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

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

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

另外,继承和成员呢?

同样的规则适用。

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

是的

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

是的

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

是的

虚拟继承会改变什么吗?

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • +1 用于描述新表达式会发生什么。这很重要。
    猜你喜欢
    • 2012-10-28
    • 2012-04-15
    • 2015-08-26
    • 2011-11-04
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    相关资源
    最近更新 更多