【发布时间】:2013-05-02 06:17:21
【问题描述】:
我在构造对象时发现了一些在异常情况下的有趣行为:
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) 抛出异常,那么
- t1 :将被完全销毁,即调用 t1 的析构函数,并释放内存。
- t11:永远不会被销毁(既不调用 t11 的析构函数也不释放内存)。
- t22:这很有趣,t22 的析构函数不会被调用这是对的,但是 t22 的内存会被释放!
如果我们从 bookentry 的构造函数 (#3) 中抛出异常,这一次,情况会有些不同:t22 永远不会被销毁(也不会调用 t22 的析构函数)或者释放内存),t11同上
我只是对#2 的句子感到困惑
test2 *t22 = 新的 test2; //2
似乎当我们从类构造函数中抛出异常时,new 表达式将确保调用相应的 delete,但是任何通过 new 表达式完全创建的对象在该异常泄漏之前(t11,或者如果我们在 #3 处抛出异常,则为 t11 和 t22)。
所以,如果我们编写如下代码并且第 5 个对象构造失败:
test2 *t2s = new test2[10];
然后,它似乎更安全一点:
- 已经构建的对象将被销毁,
- 内存将被释放。
我的问题,这是标准的 c++ 行为吗?我只是测试了 msvc 2012 和 gcc 4.4.6,看起来都实现了这样的机制。
编辑 为了让我的问题更清楚:
在某些情况下,您需要在其他正常功能中编写类似 t1.reset(new test1)[see #1 in my codes] 的代码。在这种情况下,如果构造函数抛出异常。我如何推断程序状态?有内存泄漏吗?
我的测试确保在这种情况下没有内存泄漏,但这是标准的 c++ 行为吗?
【问题讨论】:
-
MSVC 2012 绝对支持
std::unique_ptr和std::shared_ptr。我敢打赌那个版本的 GCC 也是如此。尽可能使用它们,而不是std::auto_ptr,因为它现在已被弃用。
标签: c++ exception memory memory-management constructor