我一直在尝试使用2D数组作为我的C ++类中构造函数的参数。
部首:
Matrix::Matrix(double **initComponents, int rows, int columns)
如果我只是继续定期调用new和初始化子数组,将指针传递给构造函数,它的一切都很好但是我想,我可以用初始化器创建静态2D数组并传递一个指向它的指针,到构造函数?
double A[][3] = { {2.0, 3.0, 4.0} , {1.0, 3.0, 4.0} , {2.0, 3.0, 4.0} };
Matrix *mtx = new Matrix(A, 3, 3);
不起作用:(
MS Visual Studio编译器:
" error C2664: 'Matrix::Matrix(double **,int,int)' : cannot convert parameter 1 from 'double [3][3]' to 'double ** "
任何人都可以解释原因吗?我以为它会在引用和指针之间进行自动转换。
第二个问题是,为什么我只能将A
声明为double A[][]
,为什么我必须指定第二个维度,即使我指定了所有值。
答案 0 :(得分:5)
数组确实转换为指针,但它只适用于一个级别。数组数组不会转换为指向指针的指针。
数组可以转换为指针,因为指针仍然提供了查找数组值的合理方法,但是数组数组与指针指针的根本不同。数组数组连续存储在内存中。例如,如果您有这样的定义:
int a[2][2] = {{1,2},{3,4}};
然后将[0] [0]存储在第一个存储单元中,[0] [1]存储在第二个存储单元中,a [1] [0]存储在第三个存储单元中,a [1] [1] ]在第四个。当你想查找像[i] [j]这样的特定元素时,编译器可以计算位置,因为它知道数组的大小:
int value = ((int *)a)[i*2+j];
将此与指针
的指针进行比较int a0[2] = {1,2};
int a1[2] = {3,4};
int **a = {a0,a1};
现在当你使用[i] [j]时,编译器无法直接知道在哪里看。首先必须查看[0]并查看指向的位置,然后再次查看该值。
int *ap = a[i];
int value = ap[j];
因为编译器必须使用不同的方式查找数组数组和指针指针中的值,所以不能互换使用它们。
同样,在这样的声明中:
int a[][2] = {{1,2},{3,4}};
可以省略第一个维度的大小,因为编译器会为你填写它,但这只适用于一个级别。原则上,编译器可以很好地猜测其他维度应该是什么,但它实际上是该语言中的单独规则。
如果你真的想要传递2D数组,可以使用这样的模板化构造函数来完成:
template<int rows, int cols>
Matrix(const double (&initComponents)[rows][cols])
{
// initialize matrix elements here
}
然后你甚至不需要明确地传递大小:
double A[][3] = { {2.0, 3.0, 4.0} , {1.0, 3.0, 4.0} , {2.0, 3.0, 4.0} };
Matrix *mtx = new Matrix(A);