🫒返回类型和return
2022-5-10
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 

 
return 语句将终止函数的执行并返回控制权到函数调用点,将立即执行调用点之后的代码,这个地方叫做返回地址,返回地址在执行调用时被保存在调用栈上。C++return语句返回一个返回值给调用者,而一些语言则没有提供返回值的语言特性,它们转而提供了出参数,还有另外一些语言则默认函数的最后一条语句是函数的返回值。
当函数执行到最后一条语句时会自动返回。曾经有争议是否应当在函数的中间返回(称为早期退出 “early exit”),支持的观点有证据显示从中间返回使得程序员书写起来更不易出错,也更容易理解。而反对观点则认为中间返回将导致资源得不到有效释放,而从函数的底部退出就不会跳过释放的代码。
 
C++ 通过在栈展开时由对象释放的析构函数自动调用进行资源释放,这种方式也被称为RAII(resource acquisition is initialization)资源获取即初始化,很多人认为这是一个非常糟糕的术语,认为应当用DIRR(Destruction is Resource Relinquishment)析构即资源释放,或者叫 SBRM(Scope Bound Resource Management)局部绑定资源管理。
 
有两种形式进行函数返回:
 

无返回值函数

没有返回值的return语句只能用在返回类型是void 的函数中。返回void的函数可以省略return语句,因为在这类函数的最后一条语句后面会隐式地执行return
通常情况下,void函数如果想在其中间位置提前退出,可以使用return语句,类似于break语句退出循环。
返回类型是 void 的函数也能使用 return 语句的第二种形式,不过此时 return 语句的expression必须是另一个返回void的函数,强行令void函数返回其他类型的表达式将产生编译错误。
 

有返回值函数

return 语句的第二种形式提供了函数的结果。只要函数的返回类型不是 void,则函数内的每条return语句就必须返回一个值,且返回值的类型必须与函数的返回类型相同,或者能隐式地转换成函数的返回类型(main函数例外)。
  • return 语句没有返回值是错误的,编译器能检测到这个错误
  • 在含有 return 语句的循环后面应该也有一条 return 语句,否则程序就是错误的,但很多编译器无法发现此错误。
 
函数返回一个值的方式和初始化一个变量或形参的方式完全一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。如果函数返回引用类型,则该引用仅仅是它所引用对象的一个别名。
 
不要返回局部对象的引用或指针
函数不应该返回局部对象的指针或引用,因为一旦函数完成,局部对象将被释放,指针将指向一个不存在的对象。
 
如果函数返回指针、引用或类的对象,则可以使用函数调用的结果访问结果对象的成员。
 
函数的返回类型决定函数调用是否是左值。调用一个返回引用的函数得到左值,其他返回类型得到右值。可以像使用其他左值那样来使用返回引用的函数的调用,特别是,可以为返回类型是非常量引用的函数的结果赋值:
 
如果返回类型是常量引用,则不能给调用的结果赋值:
 

列表初始化返回值

C++11规定,函数可以返回用花括号包围的值的列表。同其他返回类型一样,列表也用于初始化表示函数调用结果的临时量。如果列表为空,临时量执行值初始化;否则,返回的值由函数的返回类型决定。
如果函数返回内置类型,则列表内最多包含一个值,且该值所占空间不应该大于目标类型的空间。如果函数返回类类型,由类本身定义初始值如何使用。
 

主函数main的返回值

如果函数的返回类型不是void,那么必须返回一个值,但是允许main 函数可以没有return语句直接结束。如果控制流到达了main函数的结尾处而且没有return语句,编译器会隐式地插入一条返回0的return语句。
 
main函数的返回值可以看作是状态指示器。返回0表示执行成功,返回其他值表示执行失败,其中非0值的具体含义依机器而定。为了使main函数的返回值与机器无关,头文件cstdlib定义了EXIT_SUCCESSEXIT_FAILURE这两个预处理变量,分别表示执行成功和失败。
建议使用预处理变量EXIT_SUCCESSEXIT_FAILURE表示 main 函数的执行结果
 
 

递归

如果一个函数调用了它自身,不管这种调用是直接的还是间接的,都称该函数为递归函数
notion image
在递归函数中,一定有某条路径是不包含递归调用的,否则函数会一直递归下去,直到程序栈空间耗尽为止。
相对于循环迭代,递归的效率较低,但在某些情况下使用递归可以增加代码的可读性。
  • 循环迭代适合处理线性问题(如链表,每个节点有唯一前驱、唯一后继)
  • 而递归适合处理非线性问题(如树,每个节点的前驱、后继不唯一)
main函数不能调用它自身。
 
 

返回数组指针或引用

因为数组不能被拷贝,所以函数不能返回数组,但可以返回数组的指针或引用。
返回数组指针的函数形式如下:
 
 
C++11允许使用 尾置返回类型(trailing return type) 简化上面复杂的函数声明。尾置返回类型跟在形参列表后面,并以一个 -> 符号开头。为了表示函数真正的返回类型在形参列表之后,需要在本应出现返回类型的地方添加 auto 关键字。
任何函数的定义都能使用尾置返回类型,但是这种形式更适用于返回类型比较复杂的函数。
 
如果知道函数返回的指针将指向哪个数组,可以使用decltype关键字声明返回类型。但decltype 并不会把数组类型转换成指针类型,还要在函数声明中添加一个*符号。
 
返回数组的引用,类似于指针,一般就把*换成引用&
 
  • C++
  • 函数参数函数重载和匹配
    目录