为什么运算符 new 不能构造非恒定大小的多维数组?
Why does operator new can't construct multidimensional array of non-constant size?
一维数组的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语言支持可变长度数组,它允许所有大小都是运行时值。这需要在底层进行额外的工作,比如将M
和N
的运行时值与上面示例中的数组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++类型系统的一部分。
- 在类c++中使用new声明数组
- 在将 new 与指针一起使用时,创建数组的指定长度
- 声明C++数组(带或不带 "new" 关键字)
- 使用 new 和 值进行数组初始化,但没有显式数量的元素
- 使用new创建数组而不声明大小
- 正确分配放置 new 的数组
- 如何在C++中使用 new 运算符创建对动态创建的数组的引用?
- 使用new时如何重新分配dyyanmic数组,不使用realloc删除C++?
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 使用可变模板列表初始化数组,并放置new
- 如何获取由 new 创建的数组的开始和结束
- 使用 "new" 命令在 C++ 中的类构造函数中分配 2D 数组
- 构造函数不会将使用 new 初始化的数组作为参数
- 将指针返回使用New创建的数组数组
- 使用泛型成员变量"placement new"结构/类数组的正确方法是什么?
- 将内存分配给 2D 数组时,“new int*[rowCount];”的含义是什么?是 2D 数组,是指向数组的指针数组
- 使用 Marshal.FreeHGlobal() 来释放以前在本地分配了"new"的数组?
- 向量在我的类中.错误:数组new [-fpermissive]中的圆括号初始化项
- 新增[size]对象(args ..)在数组new [-fpermissive]中添加圆括号初始化器
- 错误:数组new中的size必须是整型[-fpermissive]