为什么C++中不存在"delete [][]... multiDimensionalArray;"操作符

23

我一直在想,标准的C++语言中是否有用于删除多维数组的运算符。

如果我们已经创建了一个指向单维数组的指针

int *array = new int[size];

删除操作的样子如下:

delete [] array;

太好了。但是如果我们有一个二维数组,就不能这样做。

delete [][] twoDimenstionalArray;

相反,我们应该像这个例子中那样循环并删除项目。

有人能解释一下为什么吗?

9个回答

25

从技术上讲,C++中并不存在二维数组。您使用的是一个一维数组,每个元素都是一个一维数组,以此来模拟二维数组。因为它并不存在,所以C++无法删除它。


20

由于没有调用的方法

int **array = new int[dim1][dim2];

所有的新增和删除都必须平衡,因此使用 delete [][] 运算符没有意义。

new int[dim1][dim2] 返回大小为 dim1 类型为 int[dim2] 的数组的指针。因此 dim2 必须是编译时常量。这类似于在堆栈上分配多维数组。


1
这是相反的。dim2必须是编译时常量,而dim1则不需要,返回int()[dim2] :) 当你想象一下如果你做int v[dim1][dim2];会发生什么,并检查v衰减为指针后的类型:它是int()[dim2];你可以记住语法。 - Johannes Schaub - litb

7
在这个例子中,delete 被多次调用的原因是因为 new 也被多次调用了。对于每个 new,都必须调用一次 delete。
例如,如果我分配了 1,000,000 字节的内存,我不能后来从 200,000 到 300,000 删除条目,因为它是作为一个整块分配的,必须作为一个整块释放。

2
因此,相反的情况也成立,如果它被分配为多个块,那么它必须作为多个块被释放。 - Binary Worrier

6
你必须像你提到的例子一样循环,原因是编译器/分配器不知道需要删除多少个数组。当你分配二维数组时,你实际上创建了N个一维数组。现在必须删除每一个数组,但系统不知道有多少个。顶层数组的大小,也就是指向第二级数组的指针数组,与C中的任何其他数组一样:其大小没有被系统存储。因此,无法按照你描述的方式实现delete [][](而不显著改变语言)。

4

从语言设计的角度来看,我不确定确切的原因,但我猜测这可能与分配内存有关。当你分配内存时,你正在创建一个数组的数组,每个数组都需要被删除。

int ** mArr = new int*[10];
for(int i=0;i<10;i++)
{
   mArr[i]=new int[10];
}

我的 C++ 已经有点生疏了,我不确定这是否在语法上是正确的,但我认为它很接近。


3
虽然所有这些答案都是相关的,但我会试着解释一下为什么像delete[][] array;这样的语法可能适用于动态分配数组,以及为什么它不可能实现:
在静态分配数组上允许的语法int array[ROWS][COLS];只是程序员的抽象,实际上创建了一个一维数组int array[ROWS*COLS];。但在编译过程中(当维度大小COLSROWS必须按标准为常量时),编译器还记住了那些维度的大小,这是必要的,以便稍后使用语法array[x][y] = 45来寻址元素。编译器知道这个大小,然后使用简单的数学运算将[x][y]替换为一维数组的相应索引:[COLS*x + y]
另一方面,在动态分配数组上,如果您想要相同的多维功能(实际上是符号),则情况并非如此。由于它们的大小可以在运行时确定,因此它们还必须记住每个附加维度的大小以供以后使用,并且在整个数组的生命周期内都要记住这一点。此外,必须在此处实现系统更改以实际作为多维数组工作,保留代码中的[x][y]访问符号形式,在编译期间不使用一维符号替换它,而是在运行时稍后替换它。
因此,array = new int[ROWS][COLS]的缺席意味着不需要delete[][] array;。正如已经提到的那样,它不能用于删除您的“多维”数组,因为您的子数组(附加维度)是分别分配的(使用单独的new调用),因此它们独立于包含它们的顶部数组(array_2D),并且它们都无法同时被删除。

0

delete[] 适用于任何非标量(数组)。


不,如果您尝试删除一个交错数组,将会导致内存泄漏。 - Jacob Krall

0

您可以使用包装类来完成所有这些操作。 使用“原始”数据类型通常不是一个好的解决方案(数组应该封装在一个类中)。例如,std::vector就是一个非常好的例子。

删除应该被调用与new被调用的次数完全相同。因为你不能调用“a = new X[a][b]”,你也不能调用“delete [][]a”。

从技术上讲,这是一个很好的设计决策,防止整个n维矩阵的奇怪初始化出现。


0

我认为这很容易实现,但太危险了。可以轻松判断指针是否由new[]创建,但很难判断new[]...[](如果允许)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接