返回值
函数
一个函数的函数名既是该函数的代表,也是一个变量。由于函数名变量通常用来把函数的处理结果数据返回给调用函数,即递归调用,所以一般把函数名变量称为返回值,函数的返回值类型是在定义函数时指定的。
公式简介
函数可以有返回值,也可以没有返回值。
(1)没有返回值的函数:功能只是完成一个操作,应将返回值类型定义为void,函数体内可没有return语句。
(2)有返回值的函数:函数的最后会有一个返回值return,可以用来获取该函数执行结果返回给该函数,让外部调用该函数的。
返回值可指定,如果不指定默认返回None。
函数的返回值类型是在定义函数时指定的。return 语句中表达式的类型应与定义函数时指定的返回值类型一致。如果不一致,则以函数定义时的返回值类型为准,对 return 语句中表达式的类型自动进行转换,然后再将它返回给主调函数使用。
在调用函数时,如果需要从被调函数返回一个值供主调函数使用,那么返回值类型必须定义成非 void 型。此时被调函数中必须包含 return 语句,而且 return 后面必须要有返回值,否则就是语法错误。
一个函数中可以有多个 return 语句,但并不是所有的 return 语句都起作用。执行到哪个 return 语句,就是哪个 return 语句起作用,该 return 语句后的其他语句都不会执行。
return 工作原理
被调函数运行结束后才会返回主调函数,但是被调函数运行结束后系统为被调函数中的局部变量分配的内存空间就会被释放。也就是说,return 返回的那个值在被调函数运行一结束就被释放掉了,那么它是怎么返回给主调函数的呢?
事实上在执行 return 语句时系统是在内部自动创建了一个临时变量,然后将 return 要返回的那个值赋给这个临时变量。所以当被调函数运行结束后 return 后面的返回值真的就被释放掉了,最后是通过这个临时变量将值返回给主调函数的。而且定义函数时指定的返回值类型实际上指定的就是这个临时变量的类型。
这也是为什么当 return 语句中表达式的类型和函数返回值类型不一致时,将 return 的类型转换成函数返回值类型的原因。return 语句实际上就是将其后的值赋给临时变量,所以它要以临时变量的类型为准,即函数返回值的类型。
C++中的返回值
例:
函数可以有返回值,只要 return 就可以给出一个,不过常常不用它,有两个原因:
1、C/C++里返回值是复制出去的,而对于大的对象,复制的代价很高;
2、有些对象是不能复制的,至少编译器不知道怎么复制,比如数组
于是有了下面这样的函数:
bool GetObj(ObjType& obj);
bool Encode(const char* src, char* dest);
用一个参数来代替返回值,而返回值只是指示函数执行是否成功。
返回一个大对象是困难的,但这个困难存在于 C 程序中,而不是 C++ 程序中。 C 函数里较少通过返回一个指针来返回对象,因为:
1、如果指针指向栈变量,毫无疑问,要么不用这个返回值,要么是一个错误;
2、如果指针指向堆变量,需要用这个函数的程序员会好好的看文档且足够细心会调用 free,要么就是内存泄漏;
3、如果指针指向 static 变量,那么用这个函数的程序员牢牢记住“下次调用这个函数以后,上次的返回值也会跟着变”。
在C++里直接返回裸指针的话,情况并不会有什么起色,不过 C++ 有智能指针的,通常它们指向堆变量,占用的空间和裸指针一样大。考虑前面第一个函数,写成:
std::auto_ptr GetObj();
返回值如果不要,作为临时变量,会立即被析构,返回的对象被释放;如果需要,就得赋值给另一个智能指针。总之不用程序员记得,编译器会保证这个对象的释放。
考虑第二个函数,稍微有一点麻烦,因为 auto_ptr 是不能用来持有数组的,不过,在C++的世界里,std::string 几乎总是比 char* 好用:
std::auto_ptr Encode(const char* src);
最后考虑最麻烦的情况:
bool AssembleObjList(ObjType objList[], size_t length);
这种类型的函数无论是在 C标准库里,还是在各种操作系统的 API 里,比比皆是,事实上它存在两大缺陷:
1、如果需要的数量超出给出的,要么是一个安全问题(经典的缓冲区溢出,如 strcpy),要么是失败,程序员不得不作出估计--众所周知,程序员的估计能力比他们的薪水低得多;
2、如果执行成功,到底 Assemble 了多少个?
于是我们见到了这样的函数:
bool AssembleObjList(ObjType objLIst[], size_t* lengthPtr);
这个函数通常是两步调用的:
size_t length = 0;
AssembleObjList(0, &length);
ObjType* objList = new ObjType[length];
AssembleObjList(objList, &length);
for(size_t i=0; i
这种形式能解决上面列出的两个问题,但这实在是太麻烦。我的答案仍然是--C++程序员应该用C++的库:
std::auto_ptr > AssembleObjList();
又干净,又舒服!
C++标准库里居然没有一个可以持有数组的智能指针,所以 boost库不错,可以这样:
std::pair, size_t> AssembleObjList();
可惜这个并不比标准库的解法更优秀--因为要返回数目的缘故,不过我个人更喜欢这个解,因为他更接近最优的解--传说中的 trule 手法:
TruleVector AssembleObjList();
其中 TruleVector是这样一个模板:它只有两种操作,一是构造,二是自动转型为 std::vector,而且它具有 “auto_ptr 式的所有权转移语义”。也就是说,TruleVector除了作为数组型的返回值,你无法把他用于其它任何任务。
不过由于 std::vector具有值语义,所以写的代码还是稍微有一点不同寻常:
typedef std::vector ObjListType;
ObjListType list;
list.swap(AssembleObjList());
最后一句在有的产品上可能要写成:
list.swap(static_cast(AssembleObjList()));
这样别扭的原因,可以归咎于C++库里缺一个引用语义的线性容器。
php中的返回值
值通过使用可选的返回语句返回。任何类型都可以返回,其中包括列表和对象。这导致函数立即结束它的运行,并且将控制权传递回它被调用的行。
例子 17-11. return()的用法
函数不能返回多个值,但为了获得简单的结果,可以返回一个列表。
例子 17-12. 返回一个数组以得到多个返回值
从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用操作符 & :
例子 17-13. 由函数返回一个引用
参考资料
最新修订时间:2024-04-22 13:28
目录
概述
公式简介
参考资料