【问题标题】:Clean way to cancel object creation取消对象创建的干净方法
【发布时间】:2011-09-29 10:33:13
【问题描述】:

我想知道如何停止/取消对象的创建,由new() 提出。也许如果某些先决条件失败并且不需要该对象。

  • new之前检查?
  • 在构造函数内检查,返回null什么的特殊,不知道怎么处理...
  • new 成功并且对象处于活动状态后进行检查。调用成员函数myObj->Init()。如果失败则销毁对象?

【问题讨论】:

  • 不要专注于 new()。您控制这些情况的(干净)方法是在构造函数中,并且也将在没有新语句的情况下调用它:“Widget myWidget;”或“Widget myWidget(this_variable, that_variable)”将调用构造函数而不使用“new”。

标签: c++ object new-operator


【解决方案1】:

以上都不是。

如果由于不满足条件而无法构造对象,则构造函数应使用throw 语句抛出异常。

【讨论】:

  • 除非你用nothrow调用它。
  • @leftaroundabout: 你不能用 nothrow() 调用构造函数 - 除非它是用 throw() (stackoverflow.com/questions/1877743/…) 定义的
  • @leftaroundabout: nothrow 仅表示无法分配内存时也不例外。构造函数仍然允许抛出。
  • @leftaroundabout nothrow 仅防止在程序无法分配内存时抛出 bad_alloc。它不会阻止你的构造函数抛出任何东西
【解决方案2】:

new之前检查?

如果您的先决条件可以在对象自身的内部范围之外进行验证,并且它们在语义上属于在调用范围内,那么当然……这太棒了!

在构造函数中检查,返回null或特殊的东西,不知道如何处理...

检查构造函数,并抛出异常。像处理任何其他异常一样处理它。 最佳方法。

new 成功并且对象处于活动状态后检查。调用成员函数myObj->Init()。如果失败则销毁对象?

以这种方式放弃 RAII 是一个倒退

【讨论】:

    【解决方案3】:

    为对象的构造函数抛出异常。请注意,对象的析构函数不会被调用,不像operator delete,它将被自动调用以回收分配的内存。

    【讨论】:

    • @TomalakGeret'kal, ... 在引发异常之前已构建的那些子对象。
    • @TomalakGeret'kal, ... 除非您使用虚拟继承。
    • 怎么样?所有成员和基础都是在输入 ctor 主体之前构建的,无论您使用哪种继承,不是吗?
    • @TomalakGeret'kal,对,对不起,我混淆了虚拟碱基而不是直接碱基的初始化顺序。当你进入构造函数的主体时,所有的子对象当然已经被构造好了。
    【解决方案4】:

    也许最好是做一个总是成功的轻量级构造函数,以及做繁重工作并在错误时抛出异常的初始化函数。

    编辑。经过一些重要的反馈后,我发现了为什么我的建议不符合 RAII 要求: “资源是在初始化期间获取的,在它们可用之前没有机会使用它们”。

    我没有更改我的原始帖子,将其作为典型的设计错误示例可能会有所帮助。

    【讨论】:

    • -1:我听说过这个提议到处都是,因为显然重型构造函数是。但是现在you just lost your RAII 抛弃了使用 C++ 的巨大好处,导致 各种 的错误可能性。推荐它是危险的,IMO。
    • 没有什么危险的,RAII也不会丢失。我不建议编写必须由客户端调用的 Release 函数。析构函数应该释放在构造函数、初始化或任何地方分配的所有资源,这是显而易见的。
    • 好的,同意,RAII 丢失了,我的错。
    • @Tomalak Geret'kal 启发我,如果构造函数调用这个 init 函数,那么 RAII 究竟是如何丢失的?
    • 我是从这个答案中删除 cmets 的 第二个 mod。请保持 cmets 具有建设性、友好性和主题性。但是,我已经清理了一些东西,所以看起来人们不是在自言自语:)
    猜你喜欢
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 2017-12-22
    • 2014-03-04
    • 2014-01-15
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多