C++之返回類型用法及return語句介紹
返回類型和return語句
return 語句的作用是終止一個函數(shù)的執(zhí)行,結(jié)束當(dāng)前代碼塊中return后的語句,即return后的語句不再執(zhí)行,從當(dāng)前位置退出函數(shù)。
return語句有兩種形式:
return; return expresion;
無返回值函數(shù)
沒有返回值的return語句只能用在返回類型是void的函數(shù)中。
返回void的函數(shù)不要求非得有return語句,因?yàn)檫@類函數(shù)的最后一句后面會隱式執(zhí)行return。
// example
void swap(int &v1, int &v2){
// 如果兩個值是相等的,則不需要交換,直接退出
if(v1 == v2){
return ;
}
// 如果執(zhí)行到了這里,說明還需要繼續(xù)完成某些功能
int tmp = v2;
v2 = v1;
v1 = tmp;
// 這里無須顯示的return語句
}
強(qiáng)行另void函數(shù)返回其他類型的表達(dá)式將會產(chǎn)生編譯錯誤??!
有返回值函數(shù)
return語句的第二種形式提供了函數(shù)的結(jié)果。只要函數(shù)的返回類型不是void,則該函數(shù)內(nèi)的每條return語句必須返回一個值。return語句返回值類型必須與函數(shù)的返回類型相同,或者能夠隱式地轉(zhuǎn)換成函數(shù)的返回類型。
盡管編譯器無法確保結(jié)果的正確性,但是可以保證每個return語句的結(jié)果類型正確。例如:
// 因?yàn)楹胁徽_的返回值 ,所以這段代碼無法編譯通過
bool str_subrange(const string &str1, const string &str2){
// 大小相同,此時用普通的相等性判斷結(jié)果作為返回值
if(str1.size() == str2.size()){
return str1 == str; // 正確:==運(yùn)算符返回的是布爾值
}
auto size = (str1.size() < str2.size()) ? str1.size() < str2.size();
// 檢查兩個string對象的對應(yīng)字符是否相等,以較短的字符串長度為限
for(decltype(size) i = 0;i != size; ++i){
if(str1[i] != str2[i])
return ; // 錯誤:沒有返回值,編譯器將會報告這一錯誤
}
// 錯誤:控制流可能尚未返回任何值就結(jié)束了函數(shù)的執(zhí)行
// 編譯器可能檢查不出來這一錯誤!
}
注意!含有return語句的循環(huán)后面應(yīng)該也要有一條return語句,如果沒有那么程序就是錯誤的!很多編譯器都無法發(fā)現(xiàn)此類錯誤!
值是如何被返回的
返回一個值的方式和初始化一個變量或形參的方式完全一樣:返回值是初始化調(diào)用點(diǎn)的一個臨時量,該臨時量就是函數(shù)調(diào)用的結(jié)果
string make_plural(size_t ctr, const string &word, const string &ending){
return (ctr > 1) ? word + ending : word;
}
該函數(shù)的返回類型是string,意味著和返回值將被拷貝到調(diào)用點(diǎn)。因此,該函數(shù)將返回word的副本或者一個未命名的臨時string對象,該對象的內(nèi)容是word和ending的和。
const string &shorterString(const string &s1, const string &s2){
return s1.size() <= s2.size() ? s1: s2;
}
其中形參和返回類型都是const string的引用,不管是調(diào)用函數(shù)還是返回結(jié)果都不會真正拷貝string對象!
不要返回局部對象的引用或指針
函數(shù)完成后,它所占用的存儲空間也會隨之被釋放掉。因此,函數(shù)終止意味著局部變量的引用將指向不再有效的內(nèi)存區(qū)域:
// 嚴(yán)重錯誤:這個函數(shù)試圖返回局部對象的引用
const string &manip(){
string ret;
if(!ret.empty())
return ret; // 錯誤,返回局部對象的引用!
else
return "empty"; // 錯誤,"empty”是一個局部變量!
}
在第二條return語句中,字符串字面值轉(zhuǎn)換成一個局部臨時string對象,對于manip來說,該對象和ret一樣都是局部的。
引用返回左值
函數(shù)的返回類型決定函數(shù)調(diào)用是否是左值。調(diào)用一個返回引用的函數(shù)得到左值,其他返回類型得到右值。可以像使用其他左值那樣來使用返回引用的函數(shù)調(diào)用,特別是,能為返回類型是非常量引用的函數(shù)的結(jié)果賦值:
char &get_val(string &str, string::size_type ix){
return str(ix); // get_val假定索引值是有效的
}
int main(){
string s("a value"); // 輸出a value
cout << s << endl; // 將s[0]的值改為A
get_value(s, 0) = 'A'; // 輸出A value
cout << s << endl;
return 0;
}
把函數(shù)調(diào)用放在賦值語句的左側(cè)可能看起來會有點(diǎn)奇怪,但其實(shí)沒什么特別的!返回值是引用,因此調(diào)用是個左值,和其他左值一樣他也能出現(xiàn)在復(fù)制運(yùn)算符的左側(cè)!
列表初始化返回值
C++11新標(biāo)準(zhǔn)規(guī)定,函數(shù)可以返回花括號包圍的值的列表。類似于其他返回結(jié)果,此處的列表也用來對表示函數(shù)返回的臨時量進(jìn)行初始化。如果列表為空,臨時量執(zhí)行值初始化;否則,返回的值有函數(shù)的返回類型決定。
vector<string> process(){
// ...
// expected actual是string對象
if(expected.empty()){
return {};
}
else if(expected == actual)
return {"functionX", "okay"};
else
return {"functionX", expected, actual};
}
如果函數(shù)返回的是內(nèi)置類型,則花括號包圍的列表最多包含一個值!而且該值所占空間不應(yīng)該大于目標(biāo)類型的空間!如果函數(shù)返回類型是類類型,由類本身定義初始值如何使用。
主函數(shù)main的返回值
如果函數(shù)的返回類型不是void,那么必須返回一個值。但是這條規(guī)定有個例外:我們允許main函數(shù)沒有return語句直接結(jié)束。如果控制到達(dá)了main函數(shù)的結(jié)尾處而且沒有return語句,編譯器將隱式地插入一條返回0的return語句。
main函數(shù)的返回值可以看作是狀態(tài)指示器。返回0表示執(zhí)行成功,返回其他值表示執(zhí)行失敗,其中非0值的具體含義根據(jù)機(jī)器來定!
返回數(shù)組指針
因?yàn)閿?shù)組不能拷貝,所以函數(shù)不能返回數(shù)組。不過,函數(shù)可以返回數(shù)組的指針或引用!要想定義一個返回數(shù)組的指針或者引用的函數(shù)比較繁瑣,但可以使用類型別名來簡化這一任務(wù)!
typedef int arrT[10]; // arrT是一個類型別名,表示的類型含有10個整數(shù)的數(shù)組 using arrT = int [10]; // arrT的等價聲明 arrT* func(int i); // func返回一個指向含有10個整數(shù)的數(shù)組的指針
arrT是含有10個整數(shù)的數(shù)組別名。因?yàn)闊o法返回數(shù)組,所以將返回類型定義成數(shù)組的指針。因此,func函數(shù)接收一個int實(shí)參,返回一個指向包含10個整數(shù)數(shù)組的指針。
聲明一個返回數(shù)組指針的函數(shù)
? 首先要區(qū)分以下的不同:
int arr[10]; //arr是一個含有10個整數(shù)的數(shù)組 int *p1[10]; //p1是一個含有10個指針的數(shù)組 數(shù)組中的值是指針 int (*p2)[10] = &arr; //p2是一個指針,它指向含有10個整數(shù)的數(shù)組
返回數(shù)組指針的函數(shù)形式如下所示:
Type (*function(parameter_list))[dimension]; // example int (*func(int i))[10];
可以按照以下順序來逐層理解該聲明的定義:
- func(int i) 調(diào)用func函數(shù)時需要int類型實(shí)參
- (*func(int i)) 對函數(shù)調(diào)用的結(jié)果進(jìn)行解引用操作
- (*func(int i))[10] 解引用func的調(diào)用將得到一個大小是10的數(shù)組
- int (*func(int i))[10]; 表示數(shù)組中的元素時int類型
#include<iostream>
using namespace std;
int (*func(int k))[10] {
int (*p)[10];
for(int i=0;i<k;i++){
(*p)[i] = i;
}
return p;
}
int main() {
int (*a)[10];
a = func(10);
for(int i=0; i<10; i++) {
cout << (*a)[i] << " ";
}
return 0;
}
使用尾置返回類型
C++11新標(biāo)準(zhǔn)有一種能簡化上述聲明的方法,就是使用尾置返回類型。然和函數(shù)的定義都能使用位置返回,但是這種形式對于返回類型比較復(fù)雜的函數(shù)最有效,比如返回類型是數(shù)組或者數(shù)組的引用。為了表示函數(shù)真正的返回類型跟在形參列表之后,應(yīng)該要在本應(yīng)該出現(xiàn)返回類型的地方放置一個auto。
// func接受一個int類型的實(shí)參,返回一個指針,該指針指向含有10個整數(shù)的數(shù)據(jù) auto func(int i) -> int(*)[10];
把函數(shù)的返回類型放在形參列表之后,可以清楚地看到func函數(shù)返回是一個指針,并且該指針指向了含有10個整數(shù)的數(shù)組。
使用decltype
假設(shè)一直到函數(shù)返回的指針指向哪個數(shù)組,就可以使用decltype關(guān)鍵字聲明返回類型。
例如,下面的函數(shù)返回一個指針,該指針根據(jù)參數(shù)i的不同指向兩個已知數(shù)組的某一個:
int odd[] = {1,3,5,7,9};
int even[] = {2,4,6,8,10};
// 返回一個指針,該指針指向含有5個整數(shù)的數(shù)組
decltype(odd) *arrPtr(itn i){
return (i%2) ? &odd : &even;
}
arrptr使用關(guān)鍵字decltype表示它的返回類型是個指針,并且該指針?biāo)赶虻膶ο笈codd類型一致。
需要注意的是,decltype并不負(fù)責(zé)把數(shù)組類型轉(zhuǎn)換成對應(yīng)的指針,所以decltype的結(jié)果是個數(shù)組,想要表示arrptr返回指針,還必須在函數(shù)聲明時加一個*符號。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C++ explicit關(guān)鍵字的應(yīng)用方法詳細(xì)講解
C++ explicit關(guān)鍵字用來修飾類的構(gòu)造函數(shù),表明該構(gòu)造函數(shù)是顯式的,既然有"顯式"那么必然就有"隱式",那么什么是顯示而什么又是隱式的呢?下面就讓我們一起來看看這方面的知識吧2013-09-09
C++ STL unordered_set 與 unordered_map的基本
在C++標(biāo)準(zhǔn)模板庫(STL)中,unordered_set和 unordered_map是基于哈希表實(shí)現(xiàn)的容器,提供了平均O(1)時間復(fù)雜度的查找、插入和刪除操作,本文給大家介紹C++ STL unordered_set與unordered_map完全指南,感興趣的朋友跟隨小編一起看看吧2026-01-01

