4 回答

TA貢獻(xiàn)1786條經(jīng)驗(yàn) 獲得超13個(gè)贊
將2D數(shù)組傳遞給函數(shù)有三種方法:
該參數(shù)是2D數(shù)組
int array[10][10];void passFunc(int a[][10]){ // ...}passFunc(array);
該參數(shù)是一個(gè)包含指針的數(shù)組
int *array[10];for(int i = 0; i < 10; i++) array[i] = new int[10];void passFunc(int *a[10]) //Array containing pointers{ // ...}passFunc(array);
該參數(shù)是指向指針的指針
int **array;array = new int *[10];for(int i = 0; i <10; i++) array[i] = new int[10];void passFunc(int **a){ // ...}passFunc(array);

TA貢獻(xiàn)1872條經(jīng)驗(yàn) 獲得超4個(gè)贊
固定尺寸
1.通過參考
template <size_t rows, size_t cols>void process_2d_array_template(int (&array)[rows][cols]){ std::cout << __func__ << std::endl; for (size_t i = 0; i < rows; ++i) { std::cout << i << ": "; for (size_t j = 0; j < cols; ++j) std::cout << array[i][j] << '\t'; std::cout << std::endl; }}
在C ++中通過引用傳遞數(shù)組而不丟失維度信息可能是最安全的,因?yàn)椴槐負(fù)?dān)心調(diào)用者傳遞不正確的維度(編譯器標(biāo)記不匹配時(shí))。但是,動(dòng)態(tài)(freestore)數(shù)組不可能實(shí)現(xiàn)這一點(diǎn); 它只適用于自動(dòng)(通常是堆棧生活)數(shù)組,即維度應(yīng)該在編譯時(shí)知道。
2.通過指針
void process_2d_array_pointer(int (*array)[5][10]){ std::cout << __func__ << std::endl; for (size_t i = 0; i < 5; ++i) { std::cout << i << ": "; for (size_t j = 0; j < 10; ++j) std::cout << (*array)[i][j] << '\t'; std::cout << std::endl; } }
前一個(gè)方法的C等價(jià)物是通過指針傳遞數(shù)組。這不應(yīng)該與通過數(shù)組的衰減指針類型(3)相混淆,這是常見的流行方法,雖然不如此安全但更靈活。與(1)類似,當(dāng)數(shù)組的所有維度都是固定的并且在編譯時(shí)已知時(shí)使用此方法。請注意,在調(diào)用函數(shù)時(shí),應(yīng)該傳遞數(shù)組的地址,process_2d_array_pointer(&a)
而不是通過衰減傳遞第一個(gè)元素的地址process_2d_array_pointer(a)
。
可變尺寸
這些都是從C繼承但不太安全,編譯器無法檢查,保證調(diào)用者傳遞所需的維度。該函數(shù)僅保留調(diào)用者傳入的維度。這些比上述更靈活,因?yàn)椴煌L度的陣列總是可以傳遞給它們。
需要記住的是,沒有將數(shù)組直接傳遞給C中的函數(shù)[在C ++中它們可以作為引用傳遞(1) ]; (2)傳遞指向數(shù)組的指針而不是數(shù)組本身。始終按原樣傳遞數(shù)組成為指針復(fù)制操作,這可以通過數(shù)組衰減到指針的特性來促進(jìn)。
3.傳遞(值)指向衰減類型的指針
// int array[][10] is just fancy notation for the same thingvoid process_2d_array(int (*array)[10], size_t rows){ std::cout << __func__ << std::endl; for (size_t i = 0; i < rows; ++i) { std::cout << i << ": "; for (size_t j = 0; j < 10; ++j) std::cout << array[i][j] << '\t'; std::cout << std::endl; }}
雖然int array[][10]
是允許的,但我不推薦它超過上面的語法,因?yàn)樯厦娴恼Z法清楚地表明標(biāo)識(shí)符array
是指向10個(gè)整數(shù)數(shù)組的單個(gè)指針,而這個(gè)語法看起來像是一個(gè)2D數(shù)組但是指向同一個(gè)一個(gè)由10個(gè)整數(shù)組成的數(shù)組。這里我們知道單行中元素的數(shù)量(即列大小,這里是10),但行數(shù)是未知的,因此作為參數(shù)傳遞。在這種情況下,由于編譯器可以標(biāo)記何時(shí)傳遞指向第二維不等于10的數(shù)組的指針,因此存在一些安全性。第一個(gè)維度是變化的部分,可以省略。請參閱此處了解為什么只允許省略第一維的原因。
4.通過指針指向指針
// int *array[10] is just fancy notation for the same thingvoid process_pointer_2_pointer(int **array, size_t rows, size_t cols){ std::cout << __func__ << std::endl; for (size_t i = 0; i < rows; ++i) { std::cout << i << ": "; for (size_t j = 0; j < cols; ++j) std::cout << array[i][j] << '\t'; std::cout << std::endl; }}
還有一種替代語法與之int *array[10]
相同int **array
。在這種語法中[10]
,它會(huì)被忽略,因?yàn)樗鼤?huì)衰減成指針,從而變?yōu)?code>int **array。也許這只是調(diào)用者的一個(gè)提示,傳遞的數(shù)組應(yīng)該至少有10列,即使那時(shí)行數(shù)也是必需的。在任何情況下,編譯器都不會(huì)標(biāo)記任何長度/大小違規(guī)(它只檢查傳遞的類型是否是指向指針的指針),因此需要行和列計(jì)數(shù)作為參數(shù)在這里有意義。
注意: (4)是最安全的選擇,因?yàn)樗鼛缀鯖]有任何類型檢查和最不方便。人們無法合法地將2D數(shù)組傳遞給此函數(shù); C-FAQ譴責(zé)通常的做法,int x[5][10]; process_pointer_2_pointer((int**)&x[0][0], 5, 10);
因?yàn)樗?a >可能會(huì)因陣列扁平化而導(dǎo)致未定義的行為。在這種方法中傳遞數(shù)組的正確方法將我們帶到了不方便的部分,即我們需要一個(gè)額外的(代理)指針數(shù)組,其每個(gè)元素指向?qū)嶋H的,要傳遞的數(shù)組的相應(yīng)行; 然后將這個(gè)代理傳遞給函數(shù)(見下文); 這一切都是為了完成與上述方法相同的工作,這些方法更安全,更清潔,也許更快。
這是一個(gè)測試上述功能的驅(qū)動(dòng)程序:
#include <iostream>// copy above functions hereint main(){ int a[5][10] = { { } }; process_2d_array_template(a); process_2d_array_pointer(&a); // <-- notice the unusual usage of addressof (&) operator on an array process_2d_array(a, 5); // works since a's first dimension decays into a pointer thereby becoming int (*)[10] int *b[5]; // surrogate for (size_t i = 0; i < 5; ++i) { b[i] = a[i]; } // another popular way to define b: here the 2D arrays dims may be non-const, runtime var // int **b = new int*[5]; // for (size_t i = 0; i < 5; ++i) b[i] = new int[10]; process_pointer_2_pointer(b, 5, 10); // process_2d_array(b, 5); // doesn't work since b's first dimension decays into a pointer thereby becoming int**}

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超10個(gè)贊
對shengy的第一個(gè)建議的修改,你可以使用模板使函數(shù)接受一個(gè)多維數(shù)組變量(而不是存儲(chǔ)必須被管理和刪除的指針數(shù)組):
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;}
print語句用于顯示數(shù)組是通過引用傳遞的(通過顯示變量的地址)

TA貢獻(xiàn)1831條經(jīng)驗(yàn) 獲得超10個(gè)贊
您可以創(chuàng)建這樣的函數(shù)模板:
template<int R, int C>void myFunction(double (&myArray)[R][C]){ myArray[x][y] = 5; etc...}
然后通過R和C獲得兩個(gè)尺寸大小。將為每個(gè)數(shù)組大小創(chuàng)建不同的函數(shù),因此如果您的函數(shù)很大并且您使用各種不同的數(shù)組大小調(diào)用它,這可能會(huì)很昂貴。你可以使用它作為這樣的函數(shù)的包裝器:
void myFunction(double * arr, int R, int C){ arr[x * C + y] = 5; etc...}
它將數(shù)組視為一維,并使用算術(shù)來計(jì)算索引的偏移量。在這種情況下,您可以像這樣定義模板:
template<int C, int R>void myFunction(double (&myArray)[R][C]){ myFunction(*myArray, R, C);}
- 4 回答
- 0 關(guān)注
- 640 瀏覽
添加回答
舉報(bào)