为什么运算符 new 不能构造非恒定大小的多维数组?

Why does operator new can't construct multidimensional array of non-constant size?

本文关键字:数组 new 运算符 不能 为什么      更新时间:2023-10-16

一维数组的new操作符如下:

int n{3};
new int[n];

至少分配sizeof(int) * n个字节。但是当我想创建二维或多维数组时,只有第一维可以是非常量:

int n{3};
new int[n][3]; //ok
new int[n][n]; //error;

为什么会有这样的限制?是否有任何困难来确定,它至少是sizeof(int) * n * n字节分配?

在这种情况下,问题不在于确定分配多少内存。这部分其实很简单,正如你自己注意到的。

问题是事后组织对这样一个数组的访问。如果您知道,c++中的多维数组是作为具有索引重新映射的线性(一维)数组实现的。例如,当您声明

int a[N][M];

编译器实际上在底层创建了一个int [N * M]数组。当您稍后作为a[i][j]访问它时,后者只是隐式地转换为对a[i * M + j]的访问。c++编译器坚持在编译时知道M的值(同时注意,N的值根本不参与索引重计算公式)。

这就是为什么在数组衰减为指针的上下文中,多维数组的第一个大小无关紧要,而第二个、第三个和以后的大小必须是编译时常量的原因。这也决定了对new []施加的限制。

注:C语言支持可变长度数组,它允许所有大小都是运行时值。这需要在底层进行额外的工作,比如将MN的运行时值与上面示例中的数组a存储在一起。最终被认为不适合c++。

c++类型系统不包含有运行时限制的数组。考虑到它将对模板和重载解析产生影响,这是一件非常复杂的事情。有一些建议,但没有一个被接受为标准化。

所以T[n]不是有效的类型。然而,它可以在new -表达式中使用,因为它有一个特殊的情况。new -表达式可以是:

  • new X,其中X为类型
  • new T[n],其中T是类型表达式,n不是常量表达式。

请注意,这两种情况都是需要的,因为T[n]不是类型,但我们希望在new -表达式中允许。

第二点需要更多的解释。它实际上使用c++中缀符号,所以如果T是数组或函数类型,那么[n]将位于不同的位置。例如"new int[n][3]"为"OK",与"typedef int T[3]; new T[n]"相同。但new int[3][n]不是。

如果允许new int[3][n],返回类型是什么?int (*)[n]不是前面提到的c++类型系统的一部分。