new []/delete []并在C ++中抛出构造函数/析构函数 [英] new[] / delete[] and throwing constructors / destructors in C++

查看:126
本文介绍了new []/delete []并在C ++中抛出构造函数/析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,如果构造/销毁某些数组元素会发生什么?

What happens, in the following code, if construction / destruction of some array element throws?

X* x = new X[10]; // (1)
delete[] x;       // (2)

我知道可以防止内存泄漏,但是另外:

I know that memory leaks are prevented, but additionally:

  1. Ad(1),先前构造的元素是否被破坏?如果是,那么在这种情况下析构函数抛出该怎么办?

  1. Ad (1), are the previously constructed elements destructed? If yes, what happens if destructor throws in such a case?

Ad(2),尚未破坏的元素是否被破坏?如果是,如果析构函数再次抛出该怎么办?

Ad (2), are the not-yet-destructed elements destructed? If yes, what happens if destructor throws again?

推荐答案

  1. 是的,如果x[5]的构造函数抛出,那么已经成功构建的五个数组元素x[0]..x[4]将被正确销毁.

  1. Yes, if the constructor of x[5] throws, then the five array elements x[0]..x[4] already successfully constructed will be destroyed correctly.

  • 析构函数不应抛出.如果发生析构函数 抛出,则在仍在处理先前(构造函数)异常的情况下会发生这种情况.由于不支持嵌套异常,因此会立即调用std::terminate.这是为什么析构函数不应该抛出的东西.
  • Destructors should not throw. If a destructor does throw, this happens while the previous (constructor) exception is still being handled. As nested exceptions aren't supported, std::terminate is called immediately. This is why destructors shouldn't throw.

这里有两个互斥的选项:

There are two mutually-exclusive options here:

  1. 如果您 reach 标签(2),则构造方法没有抛出.也就是说,如果成功创建x,则所有10个元素均已成功构建.在这种情况下,是的,它们都将被删除.不,您的析构函数仍然不应该抛出.

  1. If you reach label (2), the constructor didn't throw. That is, if x was successfully created, all ten elements were successfully constructed. In this case, yes, they all get deleted. No, your destructor still shouldn't throw.

如果构造函数在步骤(1)中途经过,则数组x 从未真正存在.该语言尝试为您创建它,但失败并引发异常-因此您完全无法达到(2).

If the constructor threw part-way through step (1), then the array x never really existed. The language tried to create it for you, failed, and threw an exception - so you don't reach (2) at all.

要理解的关键是x要么存在-处于健全且可预测的状态-要么不存在.

The key thing to understand is that x either exists - in a sane and predictable state - or it doesn't.

如果构造函数失败,该语言不会给您一些无法使用的半初始化内容,因为您无论如何都无法对其进行任何操作. (您甚至无法安全地删除它,因为无法跟踪构造了哪些元素,而哪些只是随机垃圾).

The language doesn't give you some un-usable half-initialized thing, if a constructor failed, because you couldn't do anything with it anyway. (You couldn't even safely delete it, because there would be no way to track which of the elements were constructed, and which were just random garbage).

将数组视为具有十个数据成员的对象可能会有所帮助.如果要构造此类的实例,并且其中一个基类或成员构造函数抛出异常,则所有先前构造的基和成员都将以完全相同的方式销毁,并且对象永远不会开始存在.

It might help to consider the array as an object with ten data members. If you're constructing an instance of such a class, and one of the base-class or member constructors throws, all the previously-constructed bases and members are destroyed in exactly the same way and your object never starts existing.

这篇关于new []/delete []并在C ++中抛出构造函数/析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆