返回類型和 return 語句

return 語句終止當前正在執行的函數並將控制權返回到調用該函數的地方。return 語句有兩種形式:ios

return;c++

return expression;express

 不要返回局部對象的引用或指針:數組

函數完成後,它所佔用的存儲空間也隨之被釋放掉。所以函數終止意味着局部變量的引用和指針將指向再也不有效的內存區域:函數

一種典型的錯誤就是將一個指向局部變量的指針做爲函數的返回值。因爲該數組是局部變量,所以在函數返回時其數組空間已經做廢了,即指針應用一塊無心義的地址空間,因此不會有返回值。若是獲得正常的值,只能是幸運的退出函數的時候,系統只是修改了棧頂的指針,並無清內存; 因此,是有可能正常訪問到局部變量的內存的。 但由於棧是系統自動管理的,因此該內存可能會被分配給其餘函數,這樣,該內存的內容就會被覆蓋;再也不是原來的值了。spa

 1 #include <iostream>
 2 using namespace std;
 3 
 4 const string &cmp(void){
 5     const string s1 = "hdfl", s2 = "jflds";
 6     return s1 > s2 ? s1 : s2;
 7 }
 8 
 9 int main(void){
10     const string s = cmp();
11     // cout << s << endl;//錯誤,cmp 返回是一個指向被釋放的無效內存區的引用
12     return 0;
13 }

如前所述,返回局部對象的引用是錯誤的,一樣返回局部對象的指針也是錯誤的。一旦函數完成,局部對象被釋放,指針將指向一個不存在的對象。指針

 

引用返回左值:c++11

函數的返回類型決定函數調用是不是左值。調用一個返回引用的函數獲得左值,其餘返回類型獲得右值。因此能爲返回類型是很是量引用的函數的結果賦值:code

 1 #include <iostream>
 2 using namespace std;
 3 
 4 char &gel(string &str, size_t indx){
 5     return str[indx];
 6 }
 7 
 8 int main(void){
 9     string s("a value");
10     cout << s << endl;//輸出 a value
11     gel(s, 0) = 'A';//將s[0]的值改爲A
12     cout << s << endl;//輸出A value
13     return 0;
14 }

固然,若是函數返回的是常量引用,天然是不能給調用結果賦值的。對象

 

列表初始化返回值:

c++11 規定,函數能夠返回花括號包圍的值的列表。相似於返回其餘結果,此處的列表也用來對錶示函數返回的臨時變量進行初始化。若是列表爲空,臨時量執行值初始化,不然,返回的值由函數的返回類型決定:

 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 
 5 vector<string> gel(void){
 6     return {"fjls", "fjsl", "gel", "yy"};
 7 }
 8 
 9 int main(void){
10     vector<string> s = gel();
11     for(auto indx : s){
12         cout << indx << endl;
13     }
14     return 0;
15 }

若是函數返回的是內置類型,則花括號包圍的列表中最多包含一個值,並且該值所佔空間不該該大於目標類型的空間。若是函數返回的是類類型,由類自己定義初始值如何使用。

 

返回數組指針:

由於數組不能拷貝,因此函數不能返回數組。不過,函數能夠返回數組的指針或引用:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef int arrT[10];//arrT是一個類型別名,表示的類型是含有10個整數的數組
 5 // using arrT = int[10];//arrT的等價聲明
 6 typedef int arry[10][10];
 7 
 8 arrT* gel(arrT& x){//x是數組a的引用
 9     return &x;
10 }
11 
12 arrT& lou(arry& x){
13     return x[0];
14 }
15 
16 int main(void){
17     arrT a = {1, 2, 3};
18     arrT *b = gel(a);//至關於b指向a
19     for(auto indx : *b){//b是一個指針,須要解引用
20         cout << indx << " ";
21     }
22     cout << endl;
23     // 輸出 1 2 3 0 0 0 0 0 0 0
24     arry c = {{1, 2, 3}};
25     arrT &d = lou(c);//返回c的第一個數組元素的引用
26     for(auto indx : d){
27         cout << indx << " ";
28     }
29     cout << endl;
30     // 輸出 1 2 3 0 0 0 0 0 0 0
31     return 0;
32 }

固然,不使用類型別名也是能夠的,可是要麻煩一些。其聲明以下:

Type (*function(parameter_list))[dimension]

其中 Type 表示元素類型,dimension 表示數組的大小,相似於通常的數組指針聲明。(*function(parameter_list)) 兩端的括號必須存在,若是沒有則函數的返回類型將是指針的數組。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int (*gel(int (&a)[10]))[10]{//注意:返回指針不能是局部對象
 5     return &a;
 6 }
 7 
 8 int (&lou(int (&a)[10][10]))[10]{//注意:返回引用不能是局部對象
 9     return a[0];
10 }
11 
12 int main(void){
13     int a[10] = {1, 2, 3};
14     int (*b)[10] = gel(a);
15     for(auto indx : *b){
16         cout << indx << " ";
17     }
18     cout << endl;
19     //輸出 1 2 3 0 0 0 0 0 0 0
20 
21     int c[10][10] = {{1, 2, 3}};
22     int (&d)[10] = lou(c);
23     for(auto indx : d){
24         cout << indx << " ";
25     }
26     cout << endl;
27     //輸出 1 2 3 0 0 0 0 0 0 0
28     return 0;
29 }

 

尾置返回類型:

在 c++11 中還有一種能夠簡化上述 gel 函數聲明的方法,就是使用尾置返回類型。任何函數的定義都能使用尾置返回,可是這種形式對於返回類型比較複雜的函數最有效,好比返回類型是數組的指針或者數組的引用。尾置返回類型跟在形參列表後面並以一個 -> 符號開頭。爲了表示函數真正的返回類型,咱們在本應該出現返回類型的地方放置一個 auto:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 auto gel(int (&x)[10]) -> int(*)[10]{//使用尾置返回類型返回數組指針
 5     return &x;
 6 }
 7 
 8 auto lou(int (&x)[10][10]) -> int(&)[10]{//使用尾置返回類型返回數組引用
 9     return x[0];
10 }
11 
12 int main(void){
13     int a[10] = {1, 2, 3};
14     int (*b)[10] = gel(a);
15     for(auto indx : *b){//b是指針,須要解引用
16         cout << indx << " ";
17     }
18     cout << endl;
19     //輸出 1 2 3 0 0 0 0 0 0 0
20 
21     int c[10][10] = {{1,2 , 3}};
22     int (&d)[10] = lou(c);
23     for(auto indx : d){
24         cout << indx << " ";
25     }
26     cout << endl;
27     //輸出 1 2 3 0 0 0 0 0 0 0
28     return 0;
29 }

 

使用 decltype:

還有一種狀況,若是咱們知道函數返回的指針將指向哪一個數組,就可使用 decltype 關鍵字聲明返回類型:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int a[3];
 5 
 6 decltype(a) *gel(int (&x)[3]){
 7     return &x;
 8 }
 9 
10 decltype(a) &lou(int (&x)[10][3]){
11     return x[0];
12 }
13 
14 //注意:decltype(a)返回的只是一個數組,並不會將數組類型轉化成指針或者引用類型,因此還要再加一個指針或引用聲明符
15 
16 int main(void){
17     int b[] = {1, 2, 3};
18     int (*c)[3] = gel(b);
19     for(auto indx : *c){
20         cout << indx << " ";
21     }
22     cout << endl;
23     //輸出1 2 3
24 
25     int d[10][3] = {{1, 2, 3}};
26     int (&e)[3] = lou(d);
27     for(auto indx : e){
28         cout << indx << " ";
29     }
30     cout << endl;
31     //輸出1 2 3
32     return 0;
33 }
相關文章
相關標籤/搜索