将2D数组传递给C ++函数

将2D数组传递给C ++函数

我有一个函数,我想作为一个参数,一个可变大小的2D数组。

到目前为止我有这个:

void myFunction(double** myArray){
     myArray[x][y] = 5;
     etc...}

我在代码中的其他地方声明了一个数组:

double anArray[10][10];

但是,调用myFunction(anArray)给了我一个错误。

当我传入数组时,我不想复制数组。所做的任何更改都myFunction应该改变数据的状态anArray。如果我理解正确,我只想作为参数传入指向2D数组的指针。该函数还需要接受不同大小的数组。例如,[10][10][5][5]。我怎样才能做到这一点?


心有法竹
浏览 606回答 4
4回答

开满天机

将2D数组传递给函数有三种方法:该参数是2D数组int&nbsp;array[10][10];void&nbsp;passFunc(int&nbsp;a[][10]){ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...}passFunc(array);该参数是一个包含指针的数组int&nbsp;*array[10];for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;10;&nbsp;i++) &nbsp;&nbsp;&nbsp;&nbsp;array[i]&nbsp;=&nbsp;new&nbsp;int[10];void&nbsp;passFunc(int&nbsp;*a[10])&nbsp;//Array&nbsp;containing&nbsp;pointers{ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...}passFunc(array);该参数是指向指针的指针int&nbsp;**array;array&nbsp;=&nbsp;new&nbsp;int&nbsp;*[10];for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<10;&nbsp;i++) &nbsp;&nbsp;&nbsp;&nbsp;array[i]&nbsp;=&nbsp;new&nbsp;int[10];void&nbsp;passFunc(int&nbsp;**a){ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;...}passFunc(array);

守着一只汪

固定尺寸1.通过参考template&nbsp;<size_t&nbsp;rows,&nbsp;size_t&nbsp;cols>void&nbsp;process_2d_array_template(int&nbsp;(&array)[rows][cols]){ &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;__func__&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;rows;&nbsp;++i) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;i&nbsp;<<&nbsp;":&nbsp;"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;<&nbsp;cols;&nbsp;++j) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;array[i][j]&nbsp;<<&nbsp;'\t'; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;}}在C ++中通过引用传递数组而不丢失维度信息可能是最安全的,因为不必担心调用者传递不正确的维度(编译器标记不匹配时)。但是,动态(freestore)数组不可能实现这一点;&nbsp;它只适用于自动(通常是堆栈生活)数组,即维度应该在编译时知道。2.通过指针void&nbsp;process_2d_array_pointer(int&nbsp;(*array)[5][10]){ &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;__func__&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;5;&nbsp;++i) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;i&nbsp;<<&nbsp;":&nbsp;"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;<&nbsp;10;&nbsp;++j) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;(*array)[i][j]&nbsp;<<&nbsp;'\t'; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}前一个方法的C等价物是通过指针传递数组。这不应该与通过数组的衰减指针类型(3)相混淆,这是常见的流行方法,虽然不如此安全但更灵活。与(1)类似,当数组的所有维度都是固定的并且在编译时已知时使用此方法。请注意,在调用函数时,应该传递数组的地址,process_2d_array_pointer(&a)而不是通过衰减传递第一个元素的地址process_2d_array_pointer(a)。可变尺寸这些都是从C继承但不太安全,编译器无法检查,保证调用者传递所需的维度。该函数仅保留调用者传入的维度。这些比上述更灵活,因为不同长度的阵列总是可以传递给它们。需要记住的是,没有将数组直接传递给C中的函数[在C ++中它们可以作为引用传递(1)&nbsp;];&nbsp;(2)传递指向数组的指针而不是数组本身。始终按原样传递数组成为指针复制操作,这可以通过数组衰减到指针的特性来促进。3.传递(值)指向衰减类型的指针//&nbsp;int&nbsp;array[][10]&nbsp;is&nbsp;just&nbsp;fancy&nbsp;notation&nbsp;for&nbsp;the&nbsp;same&nbsp;thingvoid&nbsp;process_2d_array(int&nbsp;(*array)[10],&nbsp;size_t&nbsp;rows){ &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;__func__&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;rows;&nbsp;++i) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;i&nbsp;<<&nbsp;":&nbsp;"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;<&nbsp;10;&nbsp;++j) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;array[i][j]&nbsp;<<&nbsp;'\t'; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;}}虽然int array[][10]是允许的,但我不推荐它超过上面的语法,因为上面的语法清楚地表明标识符array是指向10个整数数组的单个指针,而这个语法看起来像是一个2D数组但是指向同一个一个由10个整数组成的数组。这里我们知道单行中元素的数量(即列大小,这里是10),但行数是未知的,因此作为参数传递。在这种情况下,由于编译器可以标记何时传递指向第二维不等于10的数组的指针,因此存在一些安全性。第一个维度是变化的部分,可以省略。请参阅此处了解为什么只允许省略第一维的原因。4.通过指针指向指针//&nbsp;int&nbsp;*array[10]&nbsp;is&nbsp;just&nbsp;fancy&nbsp;notation&nbsp;for&nbsp;the&nbsp;same&nbsp;thingvoid&nbsp;process_pointer_2_pointer(int&nbsp;**array,&nbsp;size_t&nbsp;rows,&nbsp;size_t&nbsp;cols){ &nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;__func__&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;rows;&nbsp;++i) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;i&nbsp;<<&nbsp;":&nbsp;"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;j&nbsp;=&nbsp;0;&nbsp;j&nbsp;<&nbsp;cols;&nbsp;++j) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;array[i][j]&nbsp;<<&nbsp;'\t'; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout&nbsp;<<&nbsp;std::endl; &nbsp;&nbsp;&nbsp;&nbsp;}}还有一种替代语法与之int *array[10]相同int **array。在这种语法中[10],它会被忽略,因为它会衰减成指针,从而变为int **array。也许这只是调用者的一个提示,传递的数组应该至少有10列,即使那时行数也是必需的。在任何情况下,编译器都不会标记任何长度/大小违规(它只检查传递的类型是否是指向指针的指针),因此需要行和列计数作为参数在这里有意义。注意:&nbsp;(4)是最安全的选择,因为它几乎没有任何类型检查和最不方便。人们无法合法地将2D数组传递给此函数;&nbsp;C-FAQ谴责通常的做法,int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);因为它可能会因阵列扁平化而导致未定义的行为。在这种方法中传递数组的正确方法将我们带到了不方便的部分,即我们需要一个额外的(代理)指针数组,其每个元素指向实际的,要传递的数组的相应行;&nbsp;然后将这个代理传递给函数(见下文);&nbsp;这一切都是为了完成与上述方法相同的工作,这些方法更安全,更清洁,也许更快。这是一个测试上述功能的驱动程序:#include&nbsp;<iostream>//&nbsp;copy&nbsp;above&nbsp;functions&nbsp;hereint&nbsp;main(){ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a[5][10]&nbsp;=&nbsp;{&nbsp;{&nbsp;}&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;process_2d_array_template(a); &nbsp;&nbsp;&nbsp;&nbsp;process_2d_array_pointer(&a);&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;<--&nbsp;notice&nbsp;the&nbsp;unusual&nbsp;usage&nbsp;of&nbsp;addressof&nbsp;(&)&nbsp;operator&nbsp;on&nbsp;an&nbsp;array &nbsp;&nbsp;&nbsp;&nbsp;process_2d_array(a,&nbsp;5); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;works&nbsp;since&nbsp;a's&nbsp;first&nbsp;dimension&nbsp;decays&nbsp;into&nbsp;a&nbsp;pointer&nbsp;thereby&nbsp;becoming&nbsp;int&nbsp;(*)[10] &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;*b[5];&nbsp;&nbsp;//&nbsp;surrogate &nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;5;&nbsp;++i) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b[i]&nbsp;=&nbsp;a[i]; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;another&nbsp;popular&nbsp;way&nbsp;to&nbsp;define&nbsp;b:&nbsp;here&nbsp;the&nbsp;2D&nbsp;arrays&nbsp;dims&nbsp;may&nbsp;be&nbsp;non-const,&nbsp;runtime&nbsp;var &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;int&nbsp;**b&nbsp;=&nbsp;new&nbsp;int*[5]; &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;for&nbsp;(size_t&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<&nbsp;5;&nbsp;++i)&nbsp;b[i]&nbsp;=&nbsp;new&nbsp;int[10]; &nbsp;&nbsp;&nbsp;&nbsp;process_pointer_2_pointer(b,&nbsp;5,&nbsp;10); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;process_2d_array(b,&nbsp;5); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;doesn't&nbsp;work&nbsp;since&nbsp;b's&nbsp;first&nbsp;dimension&nbsp;decays&nbsp;into&nbsp;a&nbsp;pointer&nbsp;thereby&nbsp;becoming&nbsp;int**}

守候你守候我

对shengy的第一个建议的修改,你可以使用模板使函数接受一个多维数组变量(而不是存储必须被管理和删除的指针数组):template&nbsp;<size_t&nbsp;size_x,&nbsp;size_t&nbsp;size_y>void&nbsp;func(double&nbsp;(&arr)[size_x][size_y]){ &nbsp;&nbsp;&nbsp;&nbsp;printf("%p\n",&nbsp;&arr);}int&nbsp;main(){ &nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;a1[10][10]; &nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;a2[5][5]; &nbsp;&nbsp;&nbsp;&nbsp;printf("%p\n%p\n\n",&nbsp;&a1,&nbsp;&a2); &nbsp;&nbsp;&nbsp;&nbsp;func(a1); &nbsp;&nbsp;&nbsp;&nbsp;func(a2); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;}print语句用于显示数组是通过引用传递的(通过显示变量的地址)

慕哥6287543

您可以创建这样的函数模板:template<int&nbsp;R,&nbsp;int&nbsp;C>void&nbsp;myFunction(double&nbsp;(&myArray)[R][C]){ &nbsp;&nbsp;&nbsp;&nbsp;myArray[x][y]&nbsp;=&nbsp;5; &nbsp;&nbsp;&nbsp;&nbsp;etc...}然后通过R和C获得两个尺寸大小。将为每个数组大小创建不同的函数,因此如果您的函数很大并且您使用各种不同的数组大小调用它,这可能会很昂贵。你可以使用它作为这样的函数的包装器:void&nbsp;myFunction(double&nbsp;*&nbsp;arr,&nbsp;int&nbsp;R,&nbsp;int&nbsp;C){ &nbsp;&nbsp;&nbsp;&nbsp;arr[x&nbsp;*&nbsp;C&nbsp;+&nbsp;y]&nbsp;=&nbsp;5; &nbsp;&nbsp;&nbsp;&nbsp;etc...}它将数组视为一维,并使用算术来计算索引的偏移量。在这种情况下,您可以像这样定义模板:template<int&nbsp;C,&nbsp;int&nbsp;R>void&nbsp;myFunction(double&nbsp;(&myArray)[R][C]){ &nbsp;&nbsp;&nbsp;&nbsp;myFunction(*myArray,&nbsp;R,&nbsp;C);}
打开App,查看更多内容
随时随地看视频慕课网APP