因為數組不能被拷貝,所以函數不能返回數組。不過,函數可以返回數組的指針或引用。
雖然從語法上來說,要想定義一個返回數組的指針或引用的函數比較煩瑣,但是有一些方法可以簡化這一任務,其中最直接的方法是使用類型別名∶
typedef int arrT[10]; // arrT是一個類型別名,它表示的類型是含有10個整型的數組
using arrT = int[10]; // arrT的等價聲明
arrT *func(int i); // func返回一個指向含有10個整型的數組的指針
其中 arrT 是含有 10 個整數的數組的別名。
因為我們無法返回數組,所以將返回類型定義成數組的指針。因此,func 函數接受一個int 實參,返回一個指向包含 10個整數的數組的指針。
聲明一個返回數組指針的函數
要想在聲明func時不使用類型別名,我們必須牢記被定義的名字后面數組的維度:
int arr[10]; // arr是一個含有10個整型的數組
int *p1[10]; // p1是一個含有10個指針的數組
int (*p2)[10] = &arr; // p2是一個指針,它指向含有10個整數的數組
和這些聲明一樣,如果我們想定義一個返回數組指針的函數,則數組的維度必須跟在函數名字之后。
然而,函數的形參列表也跟在函數名字后面且形參列表應該先於數組的維度。因此,返回數組指針的函數形式如下所示∶
int (*func(int i))[10];
可以按照一下的順序來逐層理解該聲明的含義:
func(int i)
表示調用 func 函數時需要一個 int 類型的實參。(*func(int i))
意味着我們可以對函數調用的結果執行解引用操作。(*func(int i))[10]
表示解引用 func的調用將得到一個大小是10的數組。int (*func(int i))[10]
表示數組中的元素是int類型。
使用尾置返回類型
在C++11 新標准中還有一種可以簡化上述 func 聲明的方法,就是使用尾置返回類型(trailing return type)。
任何函數的定義都能使用尾置返回,但是這種形式對於返回類型比較復雜的函數最有效,比如返回類型是數組的指針或者數組的引用。尾置返回類型跟在形參列表后面並以一個 -> 符號開頭。為了表示函數真正的返回類型跟在形參列表之后,我們在本應該出現返回類型的地方放置一個 auto:
// func接受一個int類型的實參,返回一個指針,該指針指向含有10個整數的數組
auto func(int i) -> int(*)[10];
因為我們把函數的返回類型放在了形參列表之后,所以可以清楚地看到 func 函數返回的是一個指針,並且該指針指向了含有 10 個整數的數組。
使用decltype
還有一種情況,如果我們知道函數返回的指針將指向哪個數組,就可以使用 decltype 關鍵字聲明返回類型。例如,下面的函數返回一個指針,該指針根據參數 i 的不同指向兩個已知數組中的某一個:
int odd[] = {1, 3, 5, 7, 9};
int even[] = {0, 2, 4, 6, 8};
// 返回一個指針,該指針指向含有5個整數的數組。
decltype(odd) *arrPtr(int i){
return (i % 2) ? &odd : &even;
}
arrPtr 使用關鍵字 decltype 表示它的返回類型是個指針,並且該指針所指的對象與 odd 的類型一致。因為 odd 是數組,所以arrPtr返回一個指向含有5個整數的數組的指針。
有一個地方需要注意:decltype並不負責把數組類型轉換成對應的指針,所以 decltype 的結果是個數組,要想表示 arrPtr 返回指針還必須在函數聲明時加一個*符號。