为什么不把要返回元素直接当成函数的返回值返回呢

不把要返回元素直接当成函数的返回值返回的原因:如果把要返回元素直接当成函数的返回值返回,会使函数的返回值变得复杂,不易阅读和理解,并且会影响到使用该函数的程序的代码结构,还会使返回值的结构变得极其复杂,导致使用时难以理解和处理。

一、不把要返回元素直接当成函数的返回值返回的原因

如果把要返回元素直接当成函数的返回值返回,会使函数的返回值变得复杂,不易阅读和理解,并且如果要增加新的返回元素,则需要修改函数的返回值,这样会影响到使用该函数的程序的代码结构,不利于软件的扩展和维护,此外如果返回的元素之间有复杂的数据结构关系,例如嵌套的数据结构,还会使返回值的结构变得极其复杂,导致使用时难以理解和处理。

例如C里没有异常没有type deduction也无所谓构造函数,你的一个函数如果可能成功可能失败,通用做法是返回一个状态码,真正的返回值用传指针方式弄出去。这样基本也就是C能做到的最好效果了。C++里则完全不同,虽然传统方式差不多也是这样的,特别是某style guide这种邪教资料四处泛滥破坏历史发展进程的情况下。这个确实很无奈。C++标准前进的方向是该返回什么就返回什么,guaranteed copy elision、optional、structured binding、tuple都是可以使用的工具。直接返回该返回的对象优势也很多,不需要这个对象default constructible(可能需要std::optional / boost::optional / exception式error reporting),可以auto推导类型方便重构,部分场景下可以改进性能等等。错误报告可以像boost一样使用异常或者传指针/引用的error code来实现,一般error code的类型不会没事重构的。

二、函数返回值公式简介

函数可以有返回值,也可以没有返回值。

  • 没有返回值的函数:功能只是完成一个操作,应将返回值类型定义为void,函数体内可没有return语句。
  • 有返回值的函数:函数的最后会有一个返回值return,可以用来获取该函数执行结果返回给该函数,让外部调用该函数的。

返回值可指定,如果不指定默认返回None。函数的返回值类型是在定义函数时指定的。return 语句中表达式的类型应与定义函数时指定的返回值类型一致。如果不一致,则以函数定义时的返回值类型为准,对 return 语句中表达式的类型自动进行转换,然后再将它返回给主调函数使用。

在调用函数时,如果需要从被调函数返回一个值供主调函数使用,那么返回值类型必须定义成非 void 型。此时被调函数中必须包含 return 语句,而且 return 后面必须要有返回值,否则就是语法错误。一个函数中可以有多个 return 语句,但并不是所有的 return 语句都起作用。执行到哪个 return 语句,就是哪个 return 语句起作用,该 return 语句后的其他语句都不会执行。

三、C++中的返回值

函数可以有返回值,只要 return 就可以给出一个,不过常常不用它,有两个原因:第一,C/C++里返回值是复制出去的,而对于大的对象,复制的代价很高;第二,有些对象是不能复制的,至少编译器不知道怎么复制,比如数组。于是有了下面这样的函数:

bool GetObj(ObjType& obj);
bool Encode(const char* src, char* dest);

用一个参数来代替返回值,而返回值只是指示函数执行是否成功。返回一个大对象是困难的,但这个困难存在于 C 程序中,而不是 C++ 程序中。 C 函数里较少通过返回一个指针来返回对象,因为:

  1. 如果指针指向栈变量,毫无疑问,要么不用这个返回值,要么是一个错误。
  2. 如果指针指向堆变量,需要用这个函数的程序员会好好的看文档且足够细心会调用 free,要么就是内存泄漏。
  3. 如果指针指向 static 变量,那么用这个函数的程序员牢牢记住“下次调用这个函数以后,上次的返回值也会跟着变”。

在C++里直接返回裸指针的话,情况并不会有什么起色,不过 C++ 有智能指针的,通常它们指向堆变量,占用的空间和裸指针一样大。考虑前面第一个函数,写成:

std::auto_ptr<ObjType> GetObj();

返回值如果不要,作为临时变量,会立即被析构,返回的对象被释放;如果需要,就得赋值给另一个智能指针。总之不用程序员记得,编译器会保证这个对象的释放。

考虑第二个函数,稍微有一点麻烦,因为 auto_ptr 是不能用来持有数组的,不过,在C++的世界里,std::string 几乎总是比 char* 好用:

std::auto_ptr<std::string> Encode(const char* src);

最后考虑最麻烦的情况:

bool AssembleObjList(ObjType objList[], size_t length);

这种类型的函数无论是在 C 标准库里,还是在各种操作系统的 API 里,比比皆是,事实上它存在两大缺陷:第一,如果需要的数量超出给出的,要么是一个安全问题(经典的缓冲区溢出,如 strcpy),要么是失败,程序员不得不作出估计——众所周知,程序员的估计能力比他们的薪水低得多;第二,如果执行成功,到底 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<length; ++i)// 处理每个元素

这种形式能解决上面列出的两个问题,但这实在是太麻烦。如果用C++的库将会变得又干净,又舒服:

std::auto_ptr<std::vector<ObjType> > AssembleObjList();

延伸阅读

return 工作原理

被调函数运行结束后才会返回主调函数,但是被调函数运行结束后系统为被调函数中的局部变量分配的内存空间就会被释放。也就是说,return 返回的那个值在被调函数运行一结束就被释放掉了,那么它是怎么返回给主调函数的呢?

事实上在执行 return 语句时系统是在内部自动创建了一个临时变量,然后将 return 要返回的那个值赋给这个临时变量。所以当被调函数运行结束后 return 后面的返回值真的就被释放掉了,最后是通过这个临时变量将值返回给主调函数的。而且定义函数时指定的返回值类型实际上指定的就是这个临时变量的类型。

文章标题:为什么不把要返回元素直接当成函数的返回值返回呢,发布者:Z, ZLW,转载请注明出处:https://worktile.com/kb/p/49368

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Z, ZLW的头像Z, ZLW
上一篇 2023年4月15日
下一篇 2023年4月15日

相关推荐

  • 工程项目综合管理系统:用户推荐与评价

    国内外主流的10款工程项目综合管理系统对比:PingCode、Worktile、广联达、明源云、中望软件、Oracle Primavera、Asana、Wrike、Zoho Projects、Basecamp。 在处理复杂的工程项目时,选择合适的综合管理系统可能是一个令人头痛的问题。项目延误、成本超…

    2024年8月8日
    300
  • 零成本项目管理:10款合适的免费软件推荐

    国内外主流的10款免费项目管理工具对比:PingCode、Worktile、Jira 、Wrike 、ClickUp、Trello、Asana、飞书、Tapd、Teambition。 在选择项目管理软件时,许多团队面临的最大挑战之一是成本。尤其是对于初创公司或小型企业来说,高昂的软件订阅费可能是一个…

    2024年8月8日
    400
  • 项目的什么不包含管理储备

    项目的成本计划、风险应对策略、进度计划以及范围描述是不包含管理储备的。在项目管理中,管理储备是为了应对项目中无法预见的风险而设立的一种预算,它不包含在项目的初步预算中,也不包含在项目的成本基准中。这是因为管理储备的使用需要得到高层管理人员的批准,因此,它并不属于项目经理可以自由支配的资源。在具体实施…

    2024年8月7日
    1000
  • 项目管理目标 ci目标是什么

    在项目管理中,CI目标是指持续集成目标,这是一种软件开发实践,它要求团队频繁地将代码集成到一个共享的主线中。CI目标主要包括:减少集成问题、提高软件质量、加速软件发布。 持续集成通过自动化的构建和测试,可以发现并修复集成问题,从而避免了“集成地狱”的情况。这有利于提高团队的效率,减少重复的工作,帮助…

    2024年8月7日
    700
  • 文化项目运行管理是什么

    文化项目运行管理包括:项目规划、资源配置、进度控制、成本管理、风险管理。项目规划是文化项目运行管理中最为关键的一环。它不仅涉及到项目的总体目标、阶段性目标和具体任务的明确,还包括对项目时间表、资源分配及预算的详细安排。一个科学的项目规划可以有效地指导项目的实施,确保项目按计划进行,避免资源浪费和时间…

    2024年8月7日
    400

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部