由于数组不能被拷贝,所以函数不能返回数组。不过,函数可以返回数组的指针或引用。虽然从语法上来说,想要定义一个返回数组的指针或引用的函数比较麻烦,但是任然有一些方法可以来简化这个操作,其中最简单方法就是前面谈到了类型别名:
typedef int arrT[10]; //arrT是一个类型别名,表示的类型是含有10个int的数组
using arrT = int[10]; //同上
arrT* fun(int i); //返回一个指向含有10个int数组的指针
其中arrT是含有10个整数的数组的别名。因为我们无法返回数组,所以将返回类型定义成数组的指针。因此,fun函数接受一个int实参,返回一个指向含有10个整数的数组的指针。
声明一个返回数组指针的函数
如果想在声明fun时不使用类型别名,我们就得指定名字后面的数组的维度:
int arr[10]; //arr是个含有10个整数的数组
int *p1[10]; //p1是个含有10个指针的数组
int (*p2)[10]; //p2是个指针,指向含有10个整数的数组
和申明一样,在定义一个返回数组指针的函数时,需要将维度写在函数的名字后面。但是函数的形参是在维度后面的,其形式如下:
type (*function(parameter))[dimension]
//返回类型 + ( *函数名(参数列表))[数组维度]
类似其他数组的申明,type表示元素的类型,dimesion表示数组的大小。函数必须用括号包括,形式类似上面的int(*p2)[10],这种形式才是表示指向含有10个数的数组的指针,如果不加括号,那么就形如int *p1[10],表示成了含有10个指针的数组。举个例子来说明以下如何理解这个声明形式:
int (*fun(int i))[10];
按照如下顺序来明确这个函数的意义:
fun(int i); //表示调用fun函数需要传递一个int参数
(*fun(int i)) //表示函数的返回值可以指向解引用操作
(*fun(int i))[10]; //表示解引用的结果是个大小为10的数组
int (*fun(int i))[10]; //表示数组的元素类型为int
其实说得通俗一点就是,返回数组的函数申明和定义数组的形式类似,只不过将定义数组时的数组名换成了函数名加上它的参数列表。
使用尾置返回类型
在C++11 新标准中还有一种可以简化上述申明函数的方法,就是使用尾置返回类型。任何函数的定义都可以使用尾置返回,但是这种形式对于返回类型比较复杂的函数更为有效,比如返回类型是数组的指针或者数组的引用。尾置返回类型跟在形参列表后并以一个->符号开头。为了表示函数真正的返回类型跟在形参之后,我们在本该写返回类型的地方用auto替换:
//fun接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组
auto fun(int) -> int(*)[10];
因为我们把函数的返回类型放在了形参列表之后,所以可以清楚第看到fun函数返回的是个指针,并且指针指向一个含有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) ? &add : &even; //返回一个指针数组的指针
}
arrPtr使用关键字decltype表示它返回类型是个指针,并且指针所指向的对象与odd的类型一样。所以返回类型是个指向含有5个整数的数组的指针。值得注意的是,decltype并不负责将数组类型转换成相对应的指针,所以decltype的结果是个数组,想要表示arrPtr返回指针还必须在函数声明时加一个 * 符号。