我可以为一维数组编写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
个字节?
答案 0 :(得分:3)
这种情况下的问题不在于确定要分配多少内存。这部分实际上很容易,正如你自己注意到的那样。
问题是之后组织对这样一个数组的访问。如果您知道,C ++中的多维数组实现为具有索引重映射的线性(一维)数组。例如,当您声明
时int a[N][M];
编译器实际上在底层创建了一个int [N * M]
数组。当您稍后将其作为a[i][j]
访问时,后者只是隐式转换为对a[i * M + j]
的访问权限。 C ++编译器坚持在编译时知道M
的值(同时请注意N
的值根本不参与索引重新计算公式。)
这就是为什么在数组衰减到指针的情况下,多维数组的第一个大小无关紧要,而第二个,第三个和更多的大小必须是编译时常量。这也决定了对new []
施加的限制。
P.S。 C语言支持可变长度数组,允许所有大小为运行时值。这需要额外的努力,例如将M
和N
的运行时值与上面示例中的数组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 ++类型系统的一部分。