我正在尝试完全理解C++数组init。
下面是代码片段:
int main() {
const int n= 20;
int m;
m = n+10;
int (*a)[m] = new int [n][m]; //1
int *w = new int [m]; //2
int (*b)[n] = new int [m][n]; //3
int (*d)[n] = new int [n][n]; //4
}
字符串
如果我尝试完成这段代码,我会得到错误:
error: array size in new-expression must be constant
error: the value of 'm' is not usable in a constant expression
note: 'int m' is not const
型
我读过,数组的init变量必须是一个const,但是,如果是这样,那么我有一些问题:
1.为什么可以使用非常量变量m初始化一维数组**(2)?
1.为什么可以在行数位置使用非常量变量m初始化二维数组(3)?
1.为什么不能在列号位置使用非常量变量m初始化二维数组(1)**?
以防万一,我会澄清,我不是在寻找变通办法,另一种方法,等等,只是为了理论知识。
谢谢你,谢谢
1条答案
按热度按时间kmbjn2e31#
让
a
指向一个分配了new T[n];
的(一维)数组,该数组的类型为T
。当访问第
i
个数组元素时(如a[i]
),或者甚至当计算其地址时(如a+i
),编译器必须计算 offset,即数组中的第一个字节与第i
个元素中的第一个字节之间有多少字节。这样的offset就被计算为
i * sizeof(T)
。如果sizeof(T)
是一个静态已知的常数,即在编译时已知,那么这个乘法可以变得更有效。出于这个原因,禁止那些大小不能静态预测的类型T
是有意义的。ISO C遵循这条路径。注意,数组的大小(
n
)在这里无关紧要,因为它不影响偏移量的计算。大小n
可以在运行时自由计算。我们只关心sizeof(T)
是静态已知的。好消息是对于大多数类型
T
,我们确实可以在编译时计算sizeof(T)
。如果T
是数值类型或指针,我们知道它的大小。如果它是一个类,我们知道所有成员的sizeof
,我们也知道类的大小(这将是它们的总和,加上一些填充)。但是,如果
T
本身是一个数组类型呢?如果T = U[m]
是某个类型U
呢?好吧,这里我们需要静态地知道sizeof(T)
和m
的值。这是关键点。注意,在本例中,
a = new T[n]
实际上是指a = new U[n][m]
(不,它不是U[m][n]
-语法可能会混淆):T[n]
是T
类型的n
值的数组,U[n][m]
是U
类型的m
值的数组,这是一样的最后,我们可以总结一下:在
new U[n][m]
中,n
可以在运行时自由计算,但m
必须在编译时已知。这推广到多维数组:除了第一个维度之外的所有维度都必须静态已知。
一些编译器实现了一个非标准的(非ISO C)扩展,允许在运行时计算
m
,即使这会减慢偏移量的计算。这被称为“VLA”(可变长度数组)。通常还有一个编译器标志来关闭它(-pedantic
),这样就不会无意中使用它。