函式可以透過return語句,終止函式的執行並“返回”函式呼叫的地方;並且可以給定返回值。返回值的型別由函式宣告時的“返回型別”決定。
return語句可以有兩種形式:
return;// 直接返回,無返回值
return 表示式; // 返回表示式的值
1. 無返回值
當函式返回型別為void時,表示函式沒有返回值。可以在函式中需要返回時直接執行 return語句,也可以不寫。由於返回型別為void的函式執行完最後一句,會自動加上return返回。
例如,可以將之前“兩元素值互換”的程式碼,包裝成一個函式。可以先做一個判定,假如兩者相等就直接返回,這樣可以進步執行效率。
// 元素互換
void swap(int& x, int& y)
{
if (x == y)
return; // 不需要交換,直接返回
int temp = x;
x = y;
y = temp;
}
這裡判定假如元素相等就直接返回,有些類似於流程控制中的break。最後一句程式碼後面省略了return。
2. 有返回值
假如函式返回型別不為void,那麼函式必需執行return,並且每條return必需返回一個值。返回值的型別應該跟函式返回型別一致,或者可以隱式轉換為一致。
(1)函式返回值的原理
函式在呼叫點會建立一個“臨時量”,用來留存函式呼叫的結果。當使用return語句返回時,就會用返回值去初始化這個臨時量。所以返回值的相關規則,跟變數或者形參的初始化是一致的。
之前寫過一個“比較字串長度”的isLonger函式,我們可以稍作修改,讓它可以返回較長的那個字串:
// 字串比較長度,返回較長的
string longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
int main()
{
string str1 = "hello world!", str2 = "c++ is interesting!";
cout << longerStr(str1, str2) << endl;
}
呼叫這個函式,經由判定發現str2較長,這時執行return將返回str2。因為返回型別是string,所以將用str2對一個string臨時量做初始化,執行的是值複製。終極返回的值,是str2的一個副本。
(2)返回引用型別
對於string物件,顯然做值複製並不高效。所以我們依然可以鑑戒之前的經驗,使用引用型別來做返回值的傳遞,這樣就可以避免值複製。
// 返回一個string常量物件的引用,不做值複製
const string & longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
這裡我們同樣把返回值定義成了常量引用,方式和作用跟形參完全一樣。
上面函式返回的是形參str1或者str2的引用;而函式中的形參本身又是引用型別,所以終極是實參物件的引用。
而假如返回的是一個函式內區域性變數的引用,好比:
const string & f()
{
string str = "test";
return str;
}
這樣做是不安全的:由於str是函式內部的區域性物件,函式執行完成後就銷燬了;而返回值是它的引用,相當於引用了一個不存在的物件,這可能會導致無法預料的問題。
所以,函式返回引用型別時,不能返回區域性物件的引用;同樣道理,也不應該返回指向區域性物件的指標。
(3)返回類物件後連續呼叫
假如函式返回一個類的物件,那麼我們可以繼承呼叫這個物件的成員函式,這樣就形成了“鏈式呼叫”。例如:
longerStr(str1, str2).size();
呼叫運算子,和訪問物件成員的點運算子優先順序相同,並且滿意左結合律。所以鏈式呼叫就是從左向右依次呼叫,程式碼可讀性會更高。
3. 主函式的返回值
主函式main是一個特殊函式,它是我們執行程式的進口。所以C++中對主函式的返回值也有特殊的劃定:即使返回型別不是void,主函式也可以省略return語句。假如主函式執行到結尾都沒有return語句,編譯器就會自動插入一條:
return 0;
主函式的返回值可以看做程式執行的狀態指示器:返回0表示執行成功;返回非0值則表示失敗。非0值詳細的含義依靠機器決定。
這也是為什麼之前我們在主函式中都可以不寫return。
4. 返回陣列指標
與形參的討論類似,因為陣列“不能複製”的特點,函式也無法直接返回一個數組。同樣的,我們可以使用指標或者引用來實現返回陣列的目標;通常會返回一個數組指標。
int arr[5] = { 1,2,3,4,5 };
int* pa[5]; // 指標陣列,pa是包含5個int指標的陣列
int(*ap)[5] = &arr; // 陣列指標,ap是一個指標,指向長度為5的int陣列
int(*fun(int x))[5]; // 函式宣告,fun返回值型別為陣列指標
這裡對於函式fun的宣告,我們可以進行層層解析:
l fun(int x) :函式名為fun,形參為int型別的x;
l ( * fun(int x) ):函式返回的結果,可以執行解引用操縱,說明是一個指標;
l ( * fun(int x) )[5]:函式返回結果解引用之後是一個長度為5的陣列,說明返回型別是陣列指標;
l int ( * fun(int x) )[5]:陣列中元素型別為int
陣列指標的定義比較繁瑣,為了簡化這個定義,我們可以使用關鍵字typedef來定義一個型別的別號:
typedef int arrayT[5]; // 類型別號,arrayT代表長度為5的int陣列
arrayT* fun2(int x); // fun2的返回型別是指向arrayT的指標
C++ 11新尺度還提供了另一種簡化方式,用一個->符號跟在形參列表後面,再把型別單獨提出來放到最後。這種方式叫做“尾置返回型別”。
auto fun3(int x) -> int(*)[5]; // 尾置返回型別
由於返回型別放到了末尾,所以前面的型別用了自動推斷的auto。
函式可以透過return語句,終止函式的執行並“返回”函式呼叫的地方;並且可以給定返回值。返回值的型別由函式宣告時的“返回型別”決定。
return語句可以有兩種形式:
return;// 直接返回,無返回值
return 表示式; // 返回表示式的值
1. 無返回值
當函式返回型別為void時,表示函式沒有返回值。可以在函式中需要返回時直接執行 return語句,也可以不寫。由於返回型別為void的函式執行完最後一句,會自動加上return返回。
例如,可以將之前“兩元素值互換”的程式碼,包裝成一個函式。可以先做一個判定,假如兩者相等就直接返回,這樣可以進步執行效率。
// 元素互換
void swap(int& x, int& y)
{
if (x == y)
return; // 不需要交換,直接返回
int temp = x;
x = y;
y = temp;
}
這裡判定假如元素相等就直接返回,有些類似於流程控制中的break。最後一句程式碼後面省略了return。
2. 有返回值
假如函式返回型別不為void,那麼函式必需執行return,並且每條return必需返回一個值。返回值的型別應該跟函式返回型別一致,或者可以隱式轉換為一致。
(1)函式返回值的原理
函式在呼叫點會建立一個“臨時量”,用來留存函式呼叫的結果。當使用return語句返回時,就會用返回值去初始化這個臨時量。所以返回值的相關規則,跟變數或者形參的初始化是一致的。
之前寫過一個“比較字串長度”的isLonger函式,我們可以稍作修改,讓它可以返回較長的那個字串:
// 字串比較長度,返回較長的
string longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
int main()
{
string str1 = "hello world!", str2 = "c++ is interesting!";
cout << longerStr(str1, str2) << endl;
}
呼叫這個函式,經由判定發現str2較長,這時執行return將返回str2。因為返回型別是string,所以將用str2對一個string臨時量做初始化,執行的是值複製。終極返回的值,是str2的一個副本。
(2)返回引用型別
對於string物件,顯然做值複製並不高效。所以我們依然可以鑑戒之前的經驗,使用引用型別來做返回值的傳遞,這樣就可以避免值複製。
// 返回一個string常量物件的引用,不做值複製
const string & longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
這裡我們同樣把返回值定義成了常量引用,方式和作用跟形參完全一樣。
上面函式返回的是形參str1或者str2的引用;而函式中的形參本身又是引用型別,所以終極是實參物件的引用。
而假如返回的是一個函式內區域性變數的引用,好比:
const string & f()
{
string str = "test";
return str;
}
這樣做是不安全的:由於str是函式內部的區域性物件,函式執行完成後就銷燬了;而返回值是它的引用,相當於引用了一個不存在的物件,這可能會導致無法預料的問題。
所以,函式返回引用型別時,不能返回區域性物件的引用;同樣道理,也不應該返回指向區域性物件的指標。
(3)返回類物件後連續呼叫
假如函式返回一個類的物件,那麼我們可以繼承呼叫這個物件的成員函式,這樣就形成了“鏈式呼叫”。例如:
longerStr(str1, str2).size();
呼叫運算子,和訪問物件成員的點運算子優先順序相同,並且滿意左結合律。所以鏈式呼叫就是從左向右依次呼叫,程式碼可讀性會更高。
3. 主函式的返回值
主函式main是一個特殊函式,它是我們執行程式的進口。所以C++中對主函式的返回值也有特殊的劃定:即使返回型別不是void,主函式也可以省略return語句。假如主函式執行到結尾都沒有return語句,編譯器就會自動插入一條:
return 0;
主函式的返回值可以看做程式執行的狀態指示器:返回0表示執行成功;返回非0值則表示失敗。非0值詳細的含義依靠機器決定。
這也是為什麼之前我們在主函式中都可以不寫return。
4. 返回陣列指標
與形參的討論類似,因為陣列“不能複製”的特點,函式也無法直接返回一個數組。同樣的,我們可以使用指標或者引用來實現返回陣列的目標;通常會返回一個數組指標。
int arr[5] = { 1,2,3,4,5 };
int* pa[5]; // 指標陣列,pa是包含5個int指標的陣列
int(*ap)[5] = &arr; // 陣列指標,ap是一個指標,指向長度為5的int陣列
int(*fun(int x))[5]; // 函式宣告,fun返回值型別為陣列指標
這裡對於函式fun的宣告,我們可以進行層層解析:
l fun(int x) :函式名為fun,形參為int型別的x;
l ( * fun(int x) ):函式返回的結果,可以執行解引用操縱,說明是一個指標;
l ( * fun(int x) )[5]:函式返回結果解引用之後是一個長度為5的陣列,說明返回型別是陣列指標;
l int ( * fun(int x) )[5]:陣列中元素型別為int
陣列指標的定義比較繁瑣,為了簡化這個定義,我們可以使用關鍵字typedef來定義一個型別的別號:
typedef int arrayT[5]; // 類型別號,arrayT代表長度為5的int陣列
arrayT* fun2(int x); // fun2的返回型別是指向arrayT的指標
C++ 11新尺度還提供了另一種簡化方式,用一個->符號跟在形參列表後面,再把型別單獨提出來放到最後。這種方式叫做“尾置返回型別”。
auto fun3(int x) -> int(*)[5]; // 尾置返回型別
由於返回型別放到了末尾,所以前面的型別用了自動推斷的auto。
函式可以透過return語句,終止函式的執行並“返回”函式呼叫的地方;並且可以給定返回值。返回值的型別由函式宣告時的“返回型別”決定。
return語句可以有兩種形式:
return;// 直接返回,無返回值
return 表示式; // 返回表示式的值
1. 無返回值
當函式返回型別為void時,表示函式沒有返回值。可以在函式中需要返回時直接執行 return語句,也可以不寫。由於返回型別為void的函式執行完最後一句,會自動加上return返回。
例如,可以將之前“兩元素值互換”的程式碼,包裝成一個函式。可以先做一個判定,假如兩者相等就直接返回,這樣可以進步執行效率。
// 元素互換
void swap(int& x, int& y)
{
if (x == y)
return; // 不需要交換,直接返回
int temp = x;
x = y;
y = temp;
}
這裡判定假如元素相等就直接返回,有些類似於流程控制中的break。最後一句程式碼後面省略了return。
2. 有返回值
假如函式返回型別不為void,那麼函式必需執行return,並且每條return必需返回一個值。返回值的型別應該跟函式返回型別一致,或者可以隱式轉換為一致。
(1)函式返回值的原理
函式在呼叫點會建立一個“臨時量”,用來留存函式呼叫的結果。當使用return語句返回時,就會用返回值去初始化這個臨時量。所以返回值的相關規則,跟變數或者形參的初始化是一致的。
之前寫過一個“比較字串長度”的isLonger函式,我們可以稍作修改,讓它可以返回較長的那個字串:
// 字串比較長度,返回較長的
string longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
int main()
{
string str1 = "hello world!", str2 = "c++ is interesting!";
cout << longerStr(str1, str2) << endl;
}
呼叫這個函式,經由判定發現str2較長,這時執行return將返回str2。因為返回型別是string,所以將用str2對一個string臨時量做初始化,執行的是值複製。終極返回的值,是str2的一個副本。
(2)返回引用型別
對於string物件,顯然做值複製並不高效。所以我們依然可以鑑戒之前的經驗,使用引用型別來做返回值的傳遞,這樣就可以避免值複製。
// 返回一個string常量物件的引用,不做值複製
const string & longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
這裡我們同樣把返回值定義成了常量引用,方式和作用跟形參完全一樣。
上面函式返回的是形參str1或者str2的引用;而函式中的形參本身又是引用型別,所以終極是實參物件的引用。
而假如返回的是一個函式內區域性變數的引用,好比:
const string & f()
{
string str = "test";
return str;
}
這樣做是不安全的:由於str是函式內部的區域性物件,函式執行完成後就銷燬了;而返回值是它的引用,相當於引用了一個不存在的物件,這可能會導致無法預料的問題。
所以,函式返回引用型別時,不能返回區域性物件的引用;同樣道理,也不應該返回指向區域性物件的指標。
(3)返回類物件後連續呼叫
假如函式返回一個類的物件,那麼我們可以繼承呼叫這個物件的成員函式,這樣就形成了“鏈式呼叫”。例如:
longerStr(str1, str2).size();
呼叫運算子,和訪問物件成員的點運算子優先順序相同,並且滿意左結合律。所以鏈式呼叫就是從左向右依次呼叫,程式碼可讀性會更高。
3. 主函式的返回值
主函式main是一個特殊函式,它是我們執行程式的進口。所以C++中對主函式的返回值也有特殊的劃定:即使返回型別不是void,主函式也可以省略return語句。假如主函式執行到結尾都沒有return語句,編譯器就會自動插入一條:
return 0;
主函式的返回值可以看做程式執行的狀態指示器:返回0表示執行成功;返回非0值則表示失敗。非0值詳細的含義依靠機器決定。
這也是為什麼之前我們在主函式中都可以不寫return。
4. 返回陣列指標
與形參的討論類似,因為陣列“不能複製”的特點,函式也無法直接返回一個數組。同樣的,我們可以使用指標或者引用來實現返回陣列的目標;通常會返回一個數組指標。
int arr[5] = { 1,2,3,4,5 };
int* pa[5]; // 指標陣列,pa是包含5個int指標的陣列
int(*ap)[5] = &arr; // 陣列指標,ap是一個指標,指向長度為5的int陣列
int(*fun(int x))[5]; // 函式宣告,fun返回值型別為陣列指標
這裡對於函式fun的宣告,我們可以進行層層解析:
l fun(int x) :函式名為fun,形參為int型別的x;
l ( * fun(int x) ):函式返回的結果,可以執行解引用操縱,說明是一個指標;
l ( * fun(int x) )[5]:函式返回結果解引用之後是一個長度為5的陣列,說明返回型別是陣列指標;
l int ( * fun(int x) )[5]:陣列中元素型別為int
陣列指標的定義比較繁瑣,為了簡化這個定義,我們可以使用關鍵字typedef來定義一個型別的別號:
typedef int arrayT[5]; // 類型別號,arrayT代表長度為5的int陣列
arrayT* fun2(int x); // fun2的返回型別是指向arrayT的指標
C++ 11新尺度還提供了另一種簡化方式,用一個->符號跟在形參列表後面,再把型別單獨提出來放到最後。這種方式叫做“尾置返回型別”。
auto fun3(int x) -> int(*)[5]; // 尾置返回型別
由於返回型別放到了末尾,所以前面的型別用了自動推斷的auto。
函式可以透過return語句,終止函式的執行並“返回”函式呼叫的地方;並且可以給定返回值。返回值的型別由函式宣告時的“返回型別”決定。
return語句可以有兩種形式:
return;// 直接返回,無返回值
return 表示式; // 返回表示式的值
1. 無返回值
當函式返回型別為void時,表示函式沒有返回值。可以在函式中需要返回時直接執行 return語句,也可以不寫。由於返回型別為void的函式執行完最後一句,會自動加上return返回。
例如,可以將之前“兩元素值互換”的程式碼,包裝成一個函式。可以先做一個判定,假如兩者相等就直接返回,這樣可以進步執行效率。
// 元素互換
void swap(int& x, int& y)
{
if (x == y)
return; // 不需要交換,直接返回
int temp = x;
x = y;
y = temp;
}
這裡判定假如元素相等就直接返回,有些類似於流程控制中的break。最後一句程式碼後面省略了return。
2. 有返回值
假如函式返回型別不為void,那麼函式必需執行return,並且每條return必需返回一個值。返回值的型別應該跟函式返回型別一致,或者可以隱式轉換為一致。
(1)函式返回值的原理
函式在呼叫點會建立一個“臨時量”,用來留存函式呼叫的結果。當使用return語句返回時,就會用返回值去初始化這個臨時量。所以返回值的相關規則,跟變數或者形參的初始化是一致的。
之前寫過一個“比較字串長度”的isLonger函式,我們可以稍作修改,讓它可以返回較長的那個字串:
// 字串比較長度,返回較長的
string longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
int main()
{
string str1 = "hello world!", str2 = "c++ is interesting!";
cout << longerStr(str1, str2) << endl;
}
呼叫這個函式,經由判定發現str2較長,這時執行return將返回str2。因為返回型別是string,所以將用str2對一個string臨時量做初始化,執行的是值複製。終極返回的值,是str2的一個副本。
(2)返回引用型別
對於string物件,顯然做值複製並不高效。所以我們依然可以鑑戒之前的經驗,使用引用型別來做返回值的傳遞,這樣就可以避免值複製。
// 返回一個string常量物件的引用,不做值複製
const string & longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
這裡我們同樣把返回值定義成了常量引用,方式和作用跟形參完全一樣。
上面函式返回的是形參str1或者str2的引用;而函式中的形參本身又是引用型別,所以終極是實參物件的引用。
而假如返回的是一個函式內區域性變數的引用,好比:
const string & f()
{
string str = "test";
return str;
}
這樣做是不安全的:由於str是函式內部的區域性物件,函式執行完成後就銷燬了;而返回值是它的引用,相當於引用了一個不存在的物件,這可能會導致無法預料的問題。
所以,函式返回引用型別時,不能返回區域性物件的引用;同樣道理,也不應該返回指向區域性物件的指標。
(3)返回類物件後連續呼叫
假如函式返回一個類的物件,那麼我們可以繼承呼叫這個物件的成員函式,這樣就形成了“鏈式呼叫”。例如:
longerStr(str1, str2).size();
呼叫運算子,和訪問物件成員的點運算子優先順序相同,並且滿意左結合律。所以鏈式呼叫就是從左向右依次呼叫,程式碼可讀性會更高。
3. 主函式的返回值
主函式main是一個特殊函式,它是我們執行程式的進口。所以C++中對主函式的返回值也有特殊的劃定:即使返回型別不是void,主函式也可以省略return語句。假如主函式執行到結尾都沒有return語句,編譯器就會自動插入一條:
return 0;
主函式的返回值可以看做程式執行的狀態指示器:返回0表示執行成功;返回非0值則表示失敗。非0值詳細的含義依靠機器決定。
這也是為什麼之前我們在主函式中都可以不寫return。
4. 返回陣列指標
與形參的討論類似,因為陣列“不能複製”的特點,函式也無法直接返回一個數組。同樣的,我們可以使用指標或者引用來實現返回陣列的目標;通常會返回一個數組指標。
int arr[5] = { 1,2,3,4,5 };
int* pa[5]; // 指標陣列,pa是包含5個int指標的陣列
int(*ap)[5] = &arr; // 陣列指標,ap是一個指標,指向長度為5的int陣列
int(*fun(int x))[5]; // 函式宣告,fun返回值型別為陣列指標
這裡對於函式fun的宣告,我們可以進行層層解析:
l fun(int x) :函式名為fun,形參為int型別的x;
l ( * fun(int x) ):函式返回的結果,可以執行解引用操縱,說明是一個指標;
l ( * fun(int x) )[5]:函式返回結果解引用之後是一個長度為5的陣列,說明返回型別是陣列指標;
l int ( * fun(int x) )[5]:陣列中元素型別為int
陣列指標的定義比較繁瑣,為了簡化這個定義,我們可以使用關鍵字typedef來定義一個型別的別號:
typedef int arrayT[5]; // 類型別號,arrayT代表長度為5的int陣列
arrayT* fun2(int x); // fun2的返回型別是指向arrayT的指標
C++ 11新尺度還提供了另一種簡化方式,用一個->符號跟在形參列表後面,再把型別單獨提出來放到最後。這種方式叫做“尾置返回型別”。
auto fun3(int x) -> int(*)[5]; // 尾置返回型別
由於返回型別放到了末尾,所以前面的型別用了自動推斷的auto。
函式可以透過return語句,終止函式的執行並“返回”函式呼叫的地方;並且可以給定返回值。返回值的型別由函式宣告時的“返回型別”決定。
return語句可以有兩種形式:
return;// 直接返回,無返回值
return 表示式; // 返回表示式的值
1. 無返回值
當函式返回型別為void時,表示函式沒有返回值。可以在函式中需要返回時直接執行 return語句,也可以不寫。由於返回型別為void的函式執行完最後一句,會自動加上return返回。
例如,可以將之前“兩元素值互換”的程式碼,包裝成一個函式。可以先做一個判定,假如兩者相等就直接返回,這樣可以進步執行效率。
// 元素互換
void swap(int& x, int& y)
{
if (x == y)
return; // 不需要交換,直接返回
int temp = x;
x = y;
y = temp;
}
這裡判定假如元素相等就直接返回,有些類似於流程控制中的break。最後一句程式碼後面省略了return。
2. 有返回值
假如函式返回型別不為void,那麼函式必需執行return,並且每條return必需返回一個值。返回值的型別應該跟函式返回型別一致,或者可以隱式轉換為一致。
(1)函式返回值的原理
函式在呼叫點會建立一個“臨時量”,用來留存函式呼叫的結果。當使用return語句返回時,就會用返回值去初始化這個臨時量。所以返回值的相關規則,跟變數或者形參的初始化是一致的。
之前寫過一個“比較字串長度”的isLonger函式,我們可以稍作修改,讓它可以返回較長的那個字串:
// 字串比較長度,返回較長的
string longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
int main()
{
string str1 = "hello world!", str2 = "c++ is interesting!";
cout << longerStr(str1, str2) << endl;
}
呼叫這個函式,經由判定發現str2較長,這時執行return將返回str2。因為返回型別是string,所以將用str2對一個string臨時量做初始化,執行的是值複製。終極返回的值,是str2的一個副本。
(2)返回引用型別
對於string物件,顯然做值複製並不高效。所以我們依然可以鑑戒之前的經驗,使用引用型別來做返回值的傳遞,這樣就可以避免值複製。
// 返回一個string常量物件的引用,不做值複製
const string & longerStr(const string& str1, const string& str2)
{
return str1.size() > str2.size() ? str1 : str2;
}
這裡我們同樣把返回值定義成了常量引用,方式和作用跟形參完全一樣。
上面函式返回的是形參str1或者str2的引用;而函式中的形參本身又是引用型別,所以終極是實參物件的引用。
而假如返回的是一個函式內區域性變數的引用,好比:
const string & f()
{
string str = "test";
return str;
}
這樣做是不安全的:由於str是函式內部的區域性物件,函式執行完成後就銷燬了;而返回值是它的引用,相當於引用了一個不存在的物件,這可能會導致無法預料的問題。
所以,函式返回引用型別時,不能返回區域性物件的引用;同樣道理,也不應該返回指向區域性物件的指標。
(3)返回類物件後連續呼叫
假如函式返回一個類的物件,那麼我們可以繼承呼叫這個物件的成員函式,這樣就形成了“鏈式呼叫”。例如:
longerStr(str1, str2).size();
呼叫運算子,和訪問物件成員的點運算子優先順序相同,並且滿意左結合律。所以鏈式呼叫就是從左向右依次呼叫,程式碼可讀性會更高。
3. 主函式的返回值
主函式main是一個特殊函式,它是我們執行程式的進口。所以C++中對主函式的返回值也有特殊的劃定:即使返回型別不是void,主函式也可以省略return語句。假如主函式執行到結尾都沒有return語句,編譯器就會自動插入一條:
return 0;
主函式的返回值可以看做程式執行的狀態指示器:返回0表示執行成功;返回非0值則表示失敗。非0值詳細的含義依靠機器決定。
這也是為什麼之前我們在主函式中都可以不寫return。
4. 返回陣列指標
與形參的討論類似,因為陣列“不能複製”的特點,函式也無法直接返回一個數組。同樣的,我們可以使用指標或者引用來實現返回陣列的目標;通常會返回一個數組指標。
int arr[5] = { 1,2,3,4,5 };
int* pa[5]; // 指標陣列,pa是包含5個int指標的陣列
int(*ap)[5] = &arr; // 陣列指標,ap是一個指標,指向長度為5的int陣列
int(*fun(int x))[5]; // 函式宣告,fun返回值型別為陣列指標
這裡對於函式fun的宣告,我們可以進行層層解析:
l fun(int x) :函式名為fun,形參為int型別的x;
l ( * fun(int x) ):函式返回的結果,可以執行解引用操縱,說明是一個指標;
l ( * fun(int x) )[5]:函式返回結果解引用之後是一個長度為5的陣列,說明返回型別是陣列指標;
l int ( * fun(int x) )[5]:陣列中元素型別為int
陣列指標的定義比較繁瑣,為了簡化這個定義,我們可以使用關鍵字typedef來定義一個型別的別號:
typedef int arrayT[5]; // 類型別號,arrayT代表長度為5的int陣列
arrayT* fun2(int x); // fun2的返回型別是指向arrayT的指標
C++ 11新尺度還提供了另一種簡化方式,用一個->符號跟在形參列表後面,再把型別單獨提出來放到最後。這種方式叫做“尾置返回型別”。
auto fun3(int x) -> int(*)[5]; // 尾置返回型別
由於返回型別放到了末尾,所以前面的型別用了自動推斷的auto。