FreedomLy's blog.

函数返回数组指针或数组引用

字数统计: 1.3k阅读时长: 4 min
2017/04/15 Share

因为数组不能被拷贝,所以函数不能返回数组。不过,函数可以返回数组的指针或引用。
下面就介绍几种方法:

方法一: 使用类型别名

1
2
3
4
typedef int arrT[10];       // arrT是一个类型别名,表示的类型
// 是含有10个整型的数组
using arrT = int[10]; // arrT的等价声明
arrT* func(int i); // func返回一个指向含有10个整数的数组的指针

其中arrT是含有10个整数的数组别名。因为无法返回数组,所以将返回类型定义成数组的指针。因此func函数接受一个int实参,返回一个指向包含10个整数的数组的指针。

方法二: 声明一个返回数组指针的函数

要想在声明func时不适用类型别名,我们必须牢记被定义的名字后面数组的维度:

1
2
3
int arr[10];            // arr是一个含有10个整数的数组
int *p1[10]; // p1是一个含有10个指针的数组
int (*p2)[10] = &arr; // p2是一个指针,他只想含有10个整数的数组

和这些声明一样,如果想定义一个返回数组指针的函数,则数组的维度必须跟在函数名字之后。然而,函数的形参列表也更在函数名字后面且形参列表应该咸鱼数组的维度。因此,返回数组指针的函数形式如下所示:

Type (*function(parameter_list)) [dimension]

类似于其他数组的声明,Type表示元素的类型,dimension表示数组的大小。(*function(parameter_list))两段的括号必须存在,就像定义p2时两段必须有括号一样。如果没有这对括号,函数返回的类型将是指针的数组。

举个具体点的例子,下面这个func函数的声明没有使用类型别名:

1
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

1
2
// func接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组
auto func(int i) -> int(*) [10];

因为我们把函数的返回类型放在了形参列表之后,所以可以清楚地看到func函数返回的是一个指针,并且该指针指向了含有10个整数的数组。

方法四: 使用decltype

还有一种情况,如果我们知道函数返回的指针将指向哪个数组,就可以使用decltype关键字声明返回类型。例如,下面的函数返回一个指针,该指针根据参数i的不同指向两个已知数组中的某一个:

1
2
3
4
5
6
7
int odd[] = {1, 3, 5, 7, 9};
int even[] = {0, 2, 4, 6, 8};
// 返回一个指针,该指针指向含有5个整数的数组
decltype(odd) *addPtr(int i)
{
return (i % 2) ? &odd : &even; // 返回一个指向数组的指针
}

arrPtr使用关键字decltype表示它的返回类型是个指针,并且该指针所指的对象与odd类型一致。因为odd是数组,所以arrPtr返回一个指向含有5个整数的数组的指针。有一个地方需要注意: decltype并不负责把数组类型转换成对应的指针,所以decltype的结果是个数组,想要表示arrPtr返回指针还必须在函数声明是加一个*符号。

练习

1. 编写一个程序,使其返回数组的引用并且该数组白喊10个string对象。不要使用尾置返回类型、decltype或者类型别名。

1
string (&func(string (&arr)[10])) [10];

2. 为上一题的函数再写三个声明,一个使用类型别名,另一个使用尾置返回类型,最后一个使用decltype关键字。

1
2
3
4
5
6
7
8
9
10
// 使用类型别名
using arrT = string[10];
arrT& func1(arrT& arr);

// 使用尾置返回类型
auto func2(arrT& arr)->string(&) [10];

// 使用decltype关键字
string arrS[10];
decltype(arrS) &func3(arrT& arr);

3. 修改arrPtr函数,使其返回数组的引用

1
2
3
4
5
6
int odd[] = {1, 3, 5, 7, 9};
int even[] = {0, 2, 4, 6, 8};
decltype(odd) &arrPtr(int i)
{
return (i % 2) ? odd : even;
}
CATALOG
  1. 1. 方法一: 使用类型别名
  2. 2. 方法二: 声明一个返回数组指针的函数
  3. 3. 方法三: 使用尾置返回类型
  4. 4. 方法四: 使用decltype
  5. 5. 练习
    1. 5.1. 1. 编写一个程序,使其返回数组的引用并且该数组白喊10个string对象。不要使用尾置返回类型、decltype或者类型别名。
    2. 5.2. 2. 为上一题的函数再写三个声明,一个使用类型别名,另一个使用尾置返回类型,最后一个使用decltype关键字。
    3. 5.3. 3. 修改arrPtr函数,使其返回数组的引用