【问题标题】:On new's bad allocation error, does delete still need to be called?在 new 分配错误的情况下,还需要调用 delete 吗?
【发布时间】:2017-01-19 10:11:21
【问题描述】:

使用 new 时会抛出 bad_alloc 异常。在继续之前您是否仍需要在 ptr 上调用 delete,或者您可以确定没有分配内存?

如果你使用 nothrow 版本呢?如果返回 nullptr,您能否再次确信没有分配内存?

【问题讨论】:

  • 你在说哪个“ptr”?贴一些代码。
  • 任何通过new分配内存的ptr
  • 发布。一些。代码。问题的第一部分在书面上是无法回答的,而且几乎是荒谬的。当new 抛出时,表达式评估未完成。
  • 谢谢,这就是答案。我想确保我可以确信没有发生分配。问题就这么简单。

标签: c++ new-operator bad-alloc nullptr


【解决方案1】:

当抛出异常时,您不会“继续” - 执行会跳转到 catch 处理程序。

在如下表达式中:

p = new int;

首先计算子表达式new int。如果这引发异常,则执行不会到达分配。 p 保留它以前的值(如果有)。

p = new(std::nothrow) int; 的情况下,如果分配失败,p 将变为空指针。对空指针调用delete 无效。

【讨论】:

  • 不,不是。你回答了。我在问您是否可以确信没有发生分配和/或没有分配内存。
【解决方案2】:

new 的 nothrow 版本确实通过返回一个空指针来报告错误,在这种情况下,没有分配内存,也没有构造任何对象:

T * p = new (std::nothrow) T(a, b, c);

if (p)
{
    // stuff
}

delete p;   // OK, works on null pointers, too.

或许:

if (T * p = new (std::nothrow) T(a, b, c))
{
    // stuff
    delete p;
}
else
{
    // allocation failure
}

甚至更好:

if (std::unique_ptr<T> p(new (std::nothrow) T(a, b, c)))
{
    // stuff
}

最后一个版本会在 if 块的任何出口处自动删除动态对象,这是 C++ 处理多个出口从而本地化复杂性的典型示例。

(也许应该有一个make_unique_or_null函数模板来封装这最后一点。)

【讨论】:

  • 当然,第二个例子如果// stuff可以抛出,就有内存泄漏的问题
  • @M.M:第一个例子也有这个问题。我假设您通常知道需要异常正确的代码。
  • 是的,我认为如果您的答案在某个阶段提到这一点会很好,以防初学者不清楚上一个版本的优势是什么
  • 我假设您的 try catch 将在 //stuff 和删除之前处理​​,如果还有可能 //stuff 可能会抛出。
  • @M.M:我认为这是一个红鲱鱼。最后一个版本支持多个出口,前两个不支持。异常只是多个出口关注的一小部分,您通常必须了解如何构建控制流。我认为这有点超出了这个问题的范围......?
猜你喜欢
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 2017-03-05
  • 1970-01-01
相关资源
最近更新 更多