將陣列安全地傳遞給函式的解決方法
阿新 • • 發佈:2019-02-17
注:本文是我學習C++過程中的一點心得,僅供初學者參考,老鳥就不用浪費時間來看了.
有時我們需要將整個陣列的資料傳遞給某個函式.通常大家如下定義:
int function(int arr[10]);
或者:
int function(int* arr);
其實兩者是等價的.陣列將被當作指標來傳遞.於是,下面的呼叫都是合法的(編譯時沒有任何錯誤或警告):
int a[10];
int b[5];
int c;
function(a);
function(b);
function(&c);
甚至如下呼叫也可:
function(NULL);
於是問題就來了,如何能保證傳入的陣列是一個有效的包含10個元素的陣列呢?顯然編譯器是無法對此作出保證,我們只有在函式中進行判斷了,但是這樣的判斷也是不好辦到的.看來只有在使用該函式時小心一點了.如果有其它人也會呼叫你寫的這個函式,你只有祈求上天保佑了...:)
那麼有沒有辦法來避免這種情況呢?有的,還不少,下面分別來介紹:
以下的介紹適合固定大小的陣列:
方法一:使用結構來傳遞陣列:
還是上面那個函式,請如下進行定義:
(1)定義一個結構,僅包含一個數組:
struct INT_ARR_10{
arr[10];
};
(2)使用該結構的指或者引用作為函式的引數:
int function(const struct INT_ARR_10& ai);
如果你需要從陣列返回資料就不要使用const.對於這樣定義後的函式,呼叫時再也不能隨便使用其它的型別了(除非強制,使用強制型別出現了問題可就與我無關了:)).但是為了它專門定義一個結構可能有人嫌太麻煩了.那麼請繼續往下看:
方法二:使用陣列的引用來傳遞:
定義如下:
int function(int (&arr)[10]);
有人說,這樣行嗎?請試試:
#include <stdio.h>
int function(int (&arr)[10])
{
return sizeof(arr);
}
int main()
{
int a[10];
int b[5];
int c;
function(a);
function(b);
function(&c);
function(NULL);
return 0;
}
我在VC6中編譯時出現如下錯誤:
Compiling...
arrtest.cpp
D:\My Documents\cfile\dos\arrtest.cpp(15) : error C2664: 'function' : cannot convert parameter 1 from 'int [5]' to 'int (&)[10]'
A reference that is not to 'const' cannot be bound to a non-lvalue
D:\My Documents\cfile\dos\arrtest.cpp(16) : error C2664: 'function' : cannot convert parameter 1 from 'int *' to 'int (&)[10]'
A reference that is not to 'const' cannot be bound to a non-lvalue
D:\My Documents\cfile\dos\arrtest.cpp(17) : error C2664: 'function' : cannot convert parameter 1 from 'const int' to 'int (&)[10]'
A reference that is not to 'const' cannot be bound to a non-lvalue
Error executing cl.exe.
arrtest.exe - 3 error(s), 0 warning(s)
看到了吧?除了第一個呼叫沒有錯誤外,其它三個函式呼叫全部出錯.正在的這個函式僅僅只能使用擁有10個元素的int類固定陣列來呼叫.非此型別的引數在編譯時就能發現了.
如果你欲將動態陣列傳遞給函式,使用指標自然是常用的方法,但是,在C++中使用vector模板來代替指標也是更加安全的方法.在MFC中使用CArray模板也是如此:
int function(int* arr); // 使用指標
int function(int arr[]); // 使用指標
int function(vector<int>& arr); // 使用STL的向量模板
int function(CArray<int>& arr);// 使用MFC的動態陣列模板
使用引用來傳遞引數的好處在於:引用永遠都指向一個有效的物件.你不必為它是否真實存在而擔心.
有時我們需要將整個陣列的資料傳遞給某個函式.通常大家如下定義:
int function(int arr[10]);
或者:
int function(int* arr);
其實兩者是等價的.陣列將被當作指標來傳遞.於是,下面的呼叫都是合法的(編譯時沒有任何錯誤或警告):
int a[10];
int b[5];
int c;
function(a);
function(b);
function(&c);
甚至如下呼叫也可:
function(NULL);
於是問題就來了,如何能保證傳入的陣列是一個有效的包含10個元素的陣列呢?顯然編譯器是無法對此作出保證,我們只有在函式中進行判斷了,但是這樣的判斷也是不好辦到的.看來只有在使用該函式時小心一點了.如果有其它人也會呼叫你寫的這個函式,你只有祈求上天保佑了...:)
那麼有沒有辦法來避免這種情況呢?有的,還不少,下面分別來介紹:
以下的介紹適合固定大小的陣列:
方法一:使用結構來傳遞陣列:
還是上面那個函式,請如下進行定義:
(1)定義一個結構,僅包含一個數組:
struct INT_ARR_10{
arr[10];
};
(2)使用該結構的指或者引用作為函式的引數:
int function(const struct INT_ARR_10& ai);
如果你需要從陣列返回資料就不要使用const.對於這樣定義後的函式,呼叫時再也不能隨便使用其它的型別了(除非強制,使用強制型別出現了問題可就與我無關了:)).但是為了它專門定義一個結構可能有人嫌太麻煩了.那麼請繼續往下看:
方法二:使用陣列的引用來傳遞:
定義如下:
int function(int (&arr)[10]);
有人說,這樣行嗎?請試試:
#include <stdio.h>
int function(int (&arr)[10])
{
return sizeof(arr);
}
int main()
{
int a[10];
int b[5];
int c;
function(a);
function(b);
function(&c);
function(NULL);
return 0;
}
我在VC6中編譯時出現如下錯誤:
Compiling...
arrtest.cpp
D:\My Documents\cfile\dos\arrtest.cpp(15) : error C2664: 'function' : cannot convert parameter 1 from 'int [5]' to 'int (&)[10]'
A reference that is not to 'const' cannot be bound to a non-lvalue
D:\My Documents\cfile\dos\arrtest.cpp(16) : error C2664: 'function' : cannot convert parameter 1 from 'int *' to 'int (&)[10]'
A reference that is not to 'const' cannot be bound to a non-lvalue
D:\My Documents\cfile\dos\arrtest.cpp(17) : error C2664: 'function' : cannot convert parameter 1 from 'const int' to 'int (&)[10]'
A reference that is not to 'const' cannot be bound to a non-lvalue
Error executing cl.exe.
arrtest.exe - 3 error(s), 0 warning(s)
看到了吧?除了第一個呼叫沒有錯誤外,其它三個函式呼叫全部出錯.正在的這個函式僅僅只能使用擁有10個元素的int類固定陣列來呼叫.非此型別的引數在編譯時就能發現了.
如果你欲將動態陣列傳遞給函式,使用指標自然是常用的方法,但是,在C++中使用vector模板來代替指標也是更加安全的方法.在MFC中使用CArray模板也是如此:
int function(int* arr); // 使用指標
int function(int arr[]); // 使用指標
int function(vector<int>& arr); // 使用STL的向量模板
int function(CArray<int>& arr);// 使用MFC的動態陣列模板
使用引用來傳遞引數的好處在於:引用永遠都指向一個有效的物件.你不必為它是否真實存在而擔心.
使用指標來傳遞引數的好處在於:你可以選擇是是否使用該指標,如果不需要使用該引數,只要簡單地傳入一個NULL就行了.而不必來定義一個並不使用的物件.