我有一个函数,我想把它作为一个参数,一个可变大小的二维数组。
到目前为止,我有这个:
void myFunction(double** myArray){
myArray[x][y] = 5;
etc...
}
我在代码的其他地方声明了一个数组:
double anArray[10][10];
然而,调用myFunction(anArray)会给我一个错误。
我不想在传入数组时复制它。在myFunction中所做的任何更改都应该改变anArray的状态。如果我理解正确,我只想传递一个指向2D数组的指针作为参数。该函数还需要接受不同大小的数组。比如[10][10][5][5]。我该怎么做呢?
你可以省略最左边的维度,所以你最终有两个选项:
void f1(double a[][2][3]) { ... }
void f2(double (*a)[2][3]) { ... }
double a[1][2][3];
f1(a); // ok
f2(a); // ok
指针也是如此:
// compilation error: cannot convert ‘double (*)[2][3]’ to ‘double***’
// double ***p1 = a;
// compilation error: cannot convert ‘double (*)[2][3]’ to ‘double (**)[3]’
// double (**p2)[3] = a;
double (*p3)[2][3] = a; // ok
// compilation error: array of pointers != pointer to array
// double *p4[2][3] = a;
double (*p5)[3] = a[0]; // ok
double *p6 = a[0][1]; // ok
c++标准允许将N维数组衰减为指向N-1维数组的指针,因为您可以丢失最左边的维度,但仍然能够正确访问具有N-1维信息的数组元素。
详情在这里
但是,数组和指针是不一样的:数组可以衰减为指针,但是指针不携带关于它所指向的数据的大小/配置的状态。
char **是指向包含字符指针的内存块的指针,这些字符指针本身指向字符的内存块。char[][]是一个包含字符的内存块。这对编译器如何翻译代码以及最终的性能会产生影响。
源
你可以像这样创建一个函数模板:
template<int R, int C>
void myFunction(double (&myArray)[R][C])
{
myArray[x][y] = 5;
etc...
}
然后你通过R和c有两个维度大小,每个数组大小都会创建一个不同的函数,所以如果你的函数很大,并且你用各种不同的数组大小调用它,这可能代价很高。你可以像这样使用它作为一个函数的包装器:
void myFunction(double * arr, int R, int C)
{
arr[x * C + y] = 5;
etc...
}
它将数组视为一维,并使用算术计算出索引的偏移量。在这种情况下,你可以这样定义模板:
template<int C, int R>
void myFunction(double (&myArray)[R][C])
{
myFunction(*myArray, R, C);
}
对shengy第一个建议的修改,你可以使用模板让函数接受多维数组变量(而不是存储一个必须被管理和删除的指针数组):
template <size_t size_x, size_t size_y>
void func(double (&arr)[size_x][size_y])
{
printf("%p\n", &arr);
}
int main()
{
double a1[10][10];
double a2[5][5];
printf("%p\n%p\n\n", &a1, &a2);
func(a1);
func(a2);
return 0;
}
打印语句用于显示数组是通过引用传递的(通过显示变量的地址)
你可以使用c++中的模板功能来实现这一点。我是这样做的:
template<typename T, size_t col>
T process(T a[][col], size_t row) {
...
}
这种方法的问题在于,对于您提供的每一个col值,都会使用模板实例化一个新的函数定义。
所以,
int some_mat[3][3], another_mat[4,5];
process(some_mat, 3);
process(another_mat, 4);
实例化模板两次以生成2个函数定义(其中一个col = 3,另一个col = 5)。