在
定義函式時,一定要定義函式的傳回值型態,如果函式不傳回值,則使用void表示不傳回任何數值;一旦指定函式的傳回值不為void,則在函式中一定要
使用return傳回一個數值,否則編譯器將回報錯誤。
在之前的範例中,您只是使用傳值的方式傳回函式的執行結果,事實上您也可以傳回一個指標或是參考,傳回指標通常意味著您要對這個指標所指向的記憶體位置作
取值或更動的動作,例如下面的程式中,您在函式中動態建立一個陣列,並傳回它的指標值:
#include <iostream> using namespace std;
int* createArray(int); void deleteArray(int*);
int main() { int m = 0;
cout << "陣列大小: "; cin >> m;
int *arr = createArray(m);
for(int i = 0; i < m; i++) { arr[i] = i; } for(int i = 0; i < m; i++) { cout << "arr[" << i << "] = " << arr[i] << endl; }
deleteArray(arr);
return 0; }
// 傳回建立的陣列位址 int* createArray(int m) { int *a = new int[m];
for(int i = 0; i < m; i++) { a[i] = 0; }
return a; }
void deleteArray(int* arr) { delete [] arr; }
執行結果:
陣列大小: 5
arr[0] = 0
arr[1] = 1
arr[2] = 2
arr[3] = 3
arr[4] = 4
|
由於您使用動態配置的方式,所以在使用delete之前,這塊被配置的記憶體並不會自動清除,所以您可以直接傳回
給呼叫函式的主函式,注意如果您不是使用
new來配置,則在副函式中所宣告的變數記憶體,在函式執行結束後都會自動消失,則您傳回指標值也就沒有意義,也會造成存取錯誤,因為該塊記憶體在副函式
執行完畢後已經自動回收了。
在這邊的範例您也看到了如何傳遞陣列給函式,以及如何傳回一個陣列,在C++中傳遞陣列或傳回陣列一律使用傳遞記憶體位址的方法,因為陣列名稱本身就是個
指標,儲存有
位址資訊。
在進一步討論傳參考之前,您先要瞭解到,在C++中傳遞一個物件,預設也是使用傳值的方式,例如下面這個程式:
#include <iostream> #include <string> using namespace std;
string foo();
int main() { string str; // 空字串
str = foo();
cout << "address: " << &str << endl << str << endl; return 0; }
string foo() { string s = "This is caterpillar speaking.";
cout << "address: " << &s << endl << s << endl;
return s; }
執行結果:
address: 0x22ff40
This is caterpillar speaking.
address: 0x22ff50
This is caterpillar speaking.
|
您可以發現到,兩個字串的記憶體位置並不相同,表示傳回的字串在傳值時是複製一份新的傳回,您可以改用傳參考的方
式將字串值傳回,方式如下所示:
#include <iostream> #include <string> using namespace std;
string& foo();
int main() { string &str = foo();
cout << "address: " << &str << endl << str << endl;
delete &str;
return 0; }
string& foo() { string *s = new string("This is caterpillar speaking.");
cout << "address: " << s << endl << *s << endl;
return *s; }
執行結
果:
address: 0x3d2458
This is caterpillar speaking.
address: 0x3d2458
This is caterpillar speaking.
|
使用傳參考的方式是直接告知物件的記憶體位置,而沒有作物件複製的動作,可以加快程式執行的效率,而某些情況下,
編譯器也會自行將物件的傳回結果自動設定
為傳參考,即使語法上並沒有指定,例如:
#include <iostream> #include <string> using namespace std;
string foo();
int main() { string str = foo();
cout << "address: " << &str << endl << str << endl; str = foo(); // 指定新字串,會複製一份 cout << "address: " << &str << endl << str << endl; return 0; }
string foo() { string s = "This is caterpillar speaking.";
cout << "address: " << &s << endl << s << endl;
return s; }
執行結
果:
address: 0x22ff50
This is caterpillar speaking.
address: 0x22ff50
This is caterpillar speaking.
address: 0x22ff40
This is caterpillar speaking.
address: 0x22ff50
This is caterpillar speaking.
|
在這個程式中,第一行宣告str並指定foo()傳回值時,雖然並沒有指定傳回參考,但是您可以看到兩個字串變數
的值都指向同一塊記憶體,但是編譯器會自
動判斷並以傳參考的方式來傳回這個物件,而不是使用傳值的方法傳回,這是編譯器的功能,您可以將之當作一個效率上的考量作法,但不可以將之當作一個傳參考
的方式來使用。
必須注意的是,函式中的區域變數在函式開始時被配置,在函式結束後所佔有的記憶體位址也會被清除,絕對不要傳回一個區域變數的位址給呼叫者,或是以傳參考
的方式傳回一個區域變數,因為您所存取的記憶體位址中資料是未知的,所以結果是不可預期的。 |