C++,多维数组

3
当一个多维数组被传递给函数时,为什么C++要求在参数列表中指定除第一维之外的所有维度?

因为函数无法接受数组参数。 - R. Martinho Fernandes
4个回答

11
更好的提问方式是询问为什么C++不需要指定第一个维度。原因在于对于所有的数组,你不能通过值传递的方式将数组传递给函数。如果你尝试声明一个带有数组参数的函数,编译器会将其调整为相应的指针类型。这意味着你指定的维度并不构成函数签名的一部分。例如,下面这些声明都完全相同:
void f(int *p);
void f(int p[]);
void f(int p[10]);
void f(int p[100]);

在该函数中,当导航指向p的数组时,编译器所需的唯一信息是数组元素的大小,例如在这种情况下是sizeof(int)

对于更复杂的数组,情况完全相同。以下都是相同的:

void g(Type p[][10][20]);
void g(Type (*p)[10][20]);
void g(Type p[10][10][20]);
void g(Type p[99][10][20]);

但是这些都不同于:

void g(Type p[][5][20]);

因为调整除了最外层数组维度以外的任何维度,都会影响(至少)最外层数组元素的大小,这意味着用于导航数组的指针算法必须更改。


0
例如,int a[n][m]是一个数组,其类型是长度为mint数组。换句话说,数组的长度是其类型的一部分。对于所有函数参数,编译器都需要知道它的类型。
在C++中没有多维数组这样的东西,它只是看起来像是语法。在int a[4]int b[5]中,a和b是不同的类型。

你能再具体一点说明原因吗?我只理解了其中的一部分。 - user1247347

0

0
简而言之:编译器不需要维度,因为数组会“衰变”成指针。但是编译器需要任何额外的维度来计算内存中正确的位置。
首先,您需要知道C/C++中的数组是内存中的线性连续对象,非常高效。
因为C/C++中的数组是内存中的线性连续对象,所以数组会“衰变”成指针。复制整个数组将浪费时间和内存,并且不是必需的。指针是遍历数组所需的任何内容。要遍历数组,可以使用增量运算符或任何计算,该计算评估为数组中的有效地址。您可以在数组本身中设置分隔符,例如字符串中的'\0',或者将长度单独传递给函数,以告诉您的代码数组的末尾在哪里。
对于多维数组,情况有点更加复杂。多维数组仍然只是内存中的线性连续对象!但是编译器需要有关附加维度的信息来计算内存中的正确位置,想象一下以下情况:
char array[10][10]; // 0 - 99

正确:

// formal argument tells your compiler, that each column is 10 elements long
funca(int array[10][10]) {
    // access to element 25 (2 * 10 + 4, the 10 is known through your formal argument, remember that an array is null based)
    array[2][3] = 'x'; 
}

错误:

// formal argument tells your compiler, that ech colum is 5 elements long
funcb(int array[10][5]) {
    // access to element 15 (2 * 5 * + 4, the 5 is known through your formal argument, remember that an array is null based)
    array[2][3] = 'x'; 
}

一个注释(或警告): Java 中的数组,特别是(不规则)多维数组完全不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接