当你编写代码时
double m[3][4]
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
编译器实际上会创建一个双精度数组,就好像你写成了:
double _m[] = {2, 4, 5, 7, 4, 5, 1, 12, 9, 12, 13, -4};
然而,由于C/C++类型系统的存在,编译器记住了m
的类型为double [3][4]
,特别地,它还记住了大小为3和4。
当您编写以下代码时:
m[i][j]
编译器会将其替换为
_m[i * 4 + j];
(“4”来自于“double [3][4]”中的第二个大小。)例如,
m[1][2] == 1 和 _m[1 * 4 + 2] == _m[6] == 1。
正如其他人所说,双重指针(double**)是一种不带有大小信息的不同类型。如果要将 double** a 视为一个 3 x 4 矩阵,则 a[0]、a[1] 和 a[2] 必须是指向相应行的首个元素的 double* 指针。您可以通过以下方式实现此目标:
double* rows[] = { &m[0][0], &m[1][0], &m[2][0] };
double** a = &rows[0];
一个简单的转换并不会创建上面的变量
rows
。让我介绍另一种可以定义
rows
的替代方法(但是等效的)。
double* rows[] = { &m[0][0], &m[0][0] + 4, &m[0][0] + 2 * 4};
double* rows[] = { &_m[0], &_m[4], &_m[2 * 4]};
正如你所见,只有第二个大小(即4
)是必需的。通常情况下,对于多维数组,除了第一个大小外,其余所有大小都是必需的。因此,只需要一个一维数组。
double x[4] = { 1, 2, 3, 4 };
可以隐式转换为double*
double* y = x;
使用这个事实,我们还可以写成:
double* rows[] = { _m, _m + 4, _m + 2 * 4};
实际上,_m
被转化为一个指向 m[0]
的 double*
。然后,在 _m + 4
中,_m
被转化为一个指向 m[0]
的 double*
,并且向这个指针中添加了 4
。因此,_m + 4
是一个指向 _m[4]
和后面三个 double
的指针。
到目前为止,我已经解释了为什么你不能将 double [3][4]
(或者其他任何大小)转换成 double**
。现在,我将展示在你的特定情况下,如何定义 calculate 函数。
template <int N>
void calculate(double (&m)[N][N+1]) {
}
你需要调用。
calculate(m);
编译器会为您推断大小为N
。一般来说(即当第二维不是N + 1
时),您可以编写:
template <int N, int M>
void calculate(double (&m)[N][M]) {
}
double **
需要一个指向双重指针的指针,而你没有这样的东西。你可以可能通过使用double *
并显式传递数组维度来解决问题。 - Jerry Coffindouble **
,你需要提供一个double **
而不是一个二维数组。 - Daniel Fischercalculate
函数需要一个指向数组的指针。问题在于你没有这个指针。解决方法是创建它。请阅读 Vaughn Cato 的答案。 - Drew Dormann