提问人:Ivan 提问时间:11/9/2023 最后编辑:Ivan 更新时间:11/11/2023 访问量:70
C++ 中的二维数组初始化11
Two Dimensional Array init in C++11
问:
我试图完全理解 C++ 数组初始化。
下面是代码片段:
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
我已经读过,数组初始化变量必须是常量,但是,如果是这样,那么我有一些问题:
- 为什么可以使用非常量变量 m 初始化一维数组 (2)?
- 为什么可以在行号位置使用非常量变量 m 初始化二维数组 (3)?
- 为什么不能在列号位置使用非常量变量 m 初始化二维数组 (1)?
为了以防万一,我会澄清一下,我不是在寻找解决方法、其他方法等。只是为了理论知识。
谢谢!
答:
让我们指向一个(一维)数组,该数组被分配给某种类型。a
new T[n];
T
当访问 -th 数组元素时,如 ,甚至在计算其地址时,如 ,编译器必须计算偏移量,即数组中的第一个字节与其 -th 元素中的第一个字节之间有多少字节。i
a[i]
a+i
i
例如,偏移量则计算为 .如果是一个静态已知的常量,即在编译时已知,则可以使这种乘法更有效。因此,禁止那些无法静态预测大小的类型是有意义的。ISO C++ 遵循此路径。i * sizeof(T)
sizeof(T)
T
请注意,数组 () 的大小在这里无关紧要,因为它不会影响偏移计算。可以在运行时自由计算大小。我们只关心静态已知。n
n
sizeof(T)
现在,一些好消息:对于大多数类型,我们确实可以在编译时进行计算。如果是数值类型或指针,我们知道它的大小。如果它是一个类,并且我们知道所有成员,我们也知道类的大小(这将是它们的总和,加上一些填充)。T
sizeof(T)
T
sizeof
但是,如果数组类型本身呢?如果对于某种类型怎么办?好吧,在这里我们需要静态地知道 和 的值。这是关键点。T
T = U[m]
U
sizeof(T)
m
请注意,在本例中,is 实际上是意思(不,不是 -- 语法可能会令人困惑):是 类型的值数组,并且是 类型的值数组 类型的值数组,它们是相同的。a = new T[n]
a = new U[n][m]
U[m][n]
T[n]
n
T
U[n][m]
n
m
U
最后,我们可以总结一下:in ,可以在运行时自由计算,但必须在编译时知道。new U[n][m]
n
m
这推广到多维数组:除了第一个维度之外,所有维度都必须是静态已知的。
一些编译器实现了非标准(非 ISO C++)扩展,允许在运行时进行计算,即使这会减慢偏移量的计算速度。这称为“VLA”(可变长度数组)。通常还有一个编译器标志来关闭它(),这样人们就不会无意中使用它。m
-pedantic
下一个:将枚举值转换为字符串
评论