C/C++ return

return和返回值类型

return语句结束当前正在执行的函数并将控制权返回到函数调用的地方。
return语句有两种形式:

1
2
return ;
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
8
int odd[] = {1, 3, 5, 7, 9};
int even[] = {2, 4, 6, 8, 10};


decltype(odd) *func(int i)
{
return (i%2)? &odd: &even;
}

返回指向函数的指针

和数组类似,虽然不能返回一个函数,但是可以返回指向函数类型的指针。**然后,我们必须把返回类型手动写成指针,编译器不会自动的将函数返回类型当成对应的指针类型处理。**最好的办法是使用类型别名:

1
2
using F = int(int*, int);   //F是函数,不是指针
using PF = int(*)(int*, int); //PF是指针类型

必须注意的是,和函数类型的形参不一样,返回类型不会自动的转换成指针,我们必须显式的将返回类型指定为指针。

autodecltype作用于函数指针

decltype作用于某个函数时,它返回函数类型而非指针类型,需要我们显式的加上*表示我们需要返回指针,而非函数本身。当decltyp作用于函数指针时,它返回的是函数指针类型。

参考文献

1.《C++ Primer》第五版