gpt4 book ai didi

面临异常时构造函数中的c++空闲内存分配

转载 作者:行者123 更新时间:2023-11-30 02:55:31 24 4
gpt4 key购买 nike

我在构造对象的异常情况下发现了一些有趣的行为:

class bookentry
{
public:
bookentry(){
t1.reset(new test1); //0
test1 *t11 = new test1; //1
test2 *t22 = new test2; //2
throw 1; //3
}
protected:
private:
auto_ptr<test1> t1;
auto_ptr<test2> t2;
};

根据我的测试:

如果我们从 test2 的构造函数 (#2) 中抛出异常,则

  1. t1 :将被完全销毁,即 t1 的析构函数将被调用,内存将被释放。
  2. t11:永远不会被销毁(既不调用 t11 的析构函数也不释放内存)。
  3. t22:这很有趣,t22 的析构函数不会被调用,这是对的,但是 t22 的内存将被释放!

如果我们从 bookentry 的构造函数 (#3) 中抛出一个异常,这一次,情况会有所不同:t22 将永远不会被销毁(既不会调用 t22 的析构函数或释放内存),t11同上

我只是对#2 的句子感到困惑

test2 *t22 = new test2; //2

似乎当我们从类构造函数中抛出异常时,new 表达式将确保调用相应的 delete,但是任何通过 new 表达式完全创建的对象在该异常将被泄漏之前(t11,或者如果我们在#3 处抛出异常则为 t11 和 t22)。

因此,如果我们编写如下代码并且第 5 个对象构造失败:

test2 *t2s = new test2[10];

那么,它似乎更安全一些:

  1. 已经构建的对象将被销毁,
  2. 内存将被释放。

我的问题是,这是标准的 C++ 行为吗?我刚刚测试了 msvc 2012 和 gcc 4.4.6,两者看起来都实现了这种机制。

编辑使我的问题更清楚:

在某些情况下,您需要在其他正常函数中编写类似 t1.reset(new test1) 的代码[请参阅我的代码中的#1]。在这种情况下,如果构造函数抛出异常。我如何推断程序状态?有内存泄漏吗?

我的测试确保在这种情况下没有内存泄漏,但这是标准的 c++ 行为吗?

最佳答案

规则很简单:
在该范围内完全创建的所有对象都将被销毁
上述规则不适用于指向在动态存储上分配的对象的原始指针(使用 new 分配)。它们需要显式删除d。当您使用 new 时,您明确拥有资源管理,调用 delete 来释放资源是您的工作,编译器不会为您做这件事。


好读:

Constructor failures - Herb Sutter


请注意,在 C++ 中管理资源的最佳方式是使用 RAII 和智能指针。在构造函数中更是如此。无需使用任何原始指针,只需将它们包装在智能指针中,它们将在出现此类异常时自动为您的对象进行资源管理。当您在代码示例中使用 auto_ptr 而不是原始指针时,您刚刚体验到了这种强大的功能。

关于面临异常时构造函数中的c++空闲内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16433536/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com