为什么operator new不能构造非常数大小的多维数组?

时间:2016-11-15 08:44:24

标签: c++ arrays multidimensional-array variable-length-array

我可以为一维数组编写operator 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个字节?

2 个答案:

答案 0 :(得分:3)

这种情况下的问题不在于确定要分配多少内存。这部分实际上很容易,正如你自己注意到的那样。

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

int a[N][M];

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

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

P.S。 C语言支持可变长度数组,允许所有大小为运行时值。这需要额外的努力,例如将MN的运行时值与上面示例中的数组a一起存储。这最终被认为不适合C ++。

答案 1 :(得分:1)

C ++类型系统不包含具有运行时绑定的数组。考虑到它会对模板和重载决策产生影响,这是一件非常复杂的事情。已有提案,但没有一个进展到被接受标准化。

所以T[n]不是有效类型。但是它可以在new - 表达式中使用,因为它有一个特例。 new - 表达式可以是:

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

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

第二点需要更多解释。它实际上使用C ++中缀表示法,因此如果T是数组或函数类型,[n]将位于不同的位置。例如,new int[n][3]可以,这与typedef int T[3]; new T[n]相同。但new int[3][n]不是。

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