return
和返回值类型
return
语句结束当前正在执行的函数并将控制权返回到函数调用的地方。
return
语句有两种形式:1
2return ;
return expression ;
无返回值函数
没有返回值的语句只能出现在返回值类型是void
的函数中。返回void
类型的函数不一定非得有return
语句,因为这类函数的最后一句会隐式的执行return
。
有返回值函数
只要函数的返回值不是return
,就一定得有返回值。return
语句返回值的类型必须和函数的返回类型相同,或者能隐式的转换成函数的返回类型。
值是如何返回到的
返回一个值的方式和初始化一个变量或者一个形参的方式完全一样:返回的值用于初始化调用点的一个变量,这个临时变量就是函数调用的结果。
如果函数返回引用,那么这个引用仅仅是它所引用对象的一个别名。
不要返回局部对象的引用或者指针
函数完成后,它所占用的存储空间也被释放掉了(函数的栈帧被释放了)。因此,函数终止意味着局部变量的引用将指向不再有效的内存空间,同样的,返回局部对象的指针也是错误的,函数一旦完成,局部对象被释放,指针将指向一个不存在的对象。
返回类类型的的函数和调用运算符
函数的返回值可以是应用,指针,类等对象,可以使用函数调用的结果访问结果对象的成员。
引用返回左值
函数的返回值类型决定函数调用是否是左值。调用一个返回引用的函数得到左值,其他返回类型得到右值。
列表初始化返回值
函数可以返回花括号包围的值的列表。这个列表也用来对表示函数返回的临时量进行初始化。如果列表为空,临时量进行值初始化。否则,返回的值由函数的返回类型决定。
如果函数返回的是内置类型,则花括号包围的列表最多包含一个值,而且这个值所占空间不应该大于目标类型的空间。如果函数返回的是类类型,由类本身定义初始值如何使用。
main
函数的返回值
对于main
来说,允许它没有return
语句直接结束,如果控制流到了main
函数的结尾处而没有return
语句,编译器将隐式的插入一条返回0的return
语句。
递归
如果一个函数调用了它自身,不管这种调用是直接的还是间接的,都称该函数为递归函数。
返回数组指针
因为数组不能被拷贝,所以函数不能返回数组。不过可以返回数组的指针或者引用。
声明一个返回数组指针的函数
返回数组指针的函数形式如下所示:1
Type (*function(parameter_list)) [dimension]
类似于其他数组的声明,Type表示元素的类型,dimension表示数组的大小,(*function(parameter_list))
两端的括号必须在,否则函数的返回类型就是指针的数组。如下示例:1
int (*func(int i))[10];
func
带有参数,说明它是一个函数,前面带有解引用操作,说明可以对函数调用的结果执行解引用操作,括号右面说明这是一个维度为10的数组,括号左面是数组类型。
使用尾置返回类型
可以使用尾置返回类型,任何函数的定义都能使用尾置返回,但是这种形式一般用于比较复杂的返回类型,比如数组的指针或者数组的引用。形式如下:1
auto func() -> int (*)[10];
使用decltype
可以使用decltype
声明返回值类型。比如返回一个指针时,1
2
3
4
5
6
7
8int odd[] = {1, 3, 5, 7, 9};
int even[] = {2, 4, 6, 8, 10};
decltype(odd) *func(int i)
{
return (i%2)? &odd: &even;
}
返回指向函数的指针
和数组类似,虽然不能返回一个函数,但是可以返回指向函数类型的指针。**然后,我们必须把返回类型手动写成指针,编译器不会自动的将函数返回类型当成对应的指针类型处理。**最好的办法是使用类型别名:1
2using F = int(int*, int); //F是函数,不是指针
using PF = int(*)(int*, int); //PF是指针类型
必须注意的是,和函数类型的形参不一样,返回类型不会自动的转换成指针,我们必须显式的将返回类型指定为指针。
auto
和decltype
作用于函数指针
将decltype
作用于某个函数时,它返回函数类型而非指针类型,需要我们显式的加上*
表示我们需要返回指针,而非函数本身。当decltyp
作用于函数指针时,它返回的是函数指针类型。
参考文献
1.《C++ Primer》第五版