C++ 中的二维数组初始化11

Two Dimensional Array init in C++11

提问人:Ivan 提问时间:11/9/2023 最后编辑:Ivan 更新时间:11/11/2023 访问量:70

问:

我试图完全理解 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

我已经读过,数组初始化变量必须是常量,但是,如果是这样,那么我有一些问题:

  1. 为什么可以使用非常量变量 m 初始化一维数组 (2)
  2. 为什么可以在行号位置使用非常量变量 m 初始化二维数组 (3)?
  3. 为什么不能在列号位置使用非常量变量 m 初始化二维数组 (1)?

为了以防万一,我会澄清一下,我不是在寻找解决方法、其他方法等。只是为了理论知识。

谢谢!

C++ 数组 C++11

评论

0赞 Chris Dodd 11/11/2023
C++ 不支持 C 可变长度数组,因此不能在 C++ 代码中使用它们。

答:

1赞 chi 11/11/2023 #1

让我们指向一个(一维)数组,该数组被分配给某种类型。anew T[n];T

当访问 -th 数组元素时,如 ,甚至在计算其地址时,如 ,编译器必须计算偏移量,即数组中的第一个字节与其 -th 元素中的第一个字节之间有多少字节。ia[i]a+ii

例如,偏移量则计算为 .如果是一个静态已知的常量,即在编译时已知,则可以使这种乘法更有效。因此,禁止那些无法静态预测大小的类型是有意义的。ISO C++ 遵循此路径。i * sizeof(T)sizeof(T)T

请注意,数组 () 的大小在这里无关紧要,因为它不会影响偏移计算。可以在运行时自由计算大小。我们只关心静态已知。nnsizeof(T)

现在,一些好消息:对于大多数类型,我们确实可以在编译时进行计算。如果是数值类型或指针,我们知道它的大小。如果它是一个类,并且我们知道所有成员,我们也知道类的大小(这将是它们的总和,加上一些填充)。Tsizeof(T)Tsizeof

但是,如果数组类型本身呢?如果对于某种类型怎么办?好吧,在这里我们需要静态地知道 和 的值。这是关键点。TT = U[m]Usizeof(T)m

请注意,在本例中,is 实际上是意思(不,不是 -- 语法可能会令人困惑):是 类型的值数组,并且是 类型的值数组 类型的值数组,它们是相同的。a = new T[n]a = new U[n][m]U[m][n]T[n]nTU[n][m]nmU

最后,我们可以总结一下:in ,可以在运行时自由计算,但必须在编译时知道。new U[n][m]nm

这推广到多维数组:除了第一个维度之外,所有维度都必须是静态已知的。

一些编译器实现了非标准(非 ISO C++)扩展,允许在运行时进行计算,即使这会减慢偏移量的计算速度。这称为“VLA”(可变长度数组)。通常还有一个编译器标志来关闭它(),这样人们就不会无意中使用它。m-pedantic