最新要闻
- 最新消息:零余额账户是什么意思_零余额帐户是什么意思啊
- 天天讯息:AMD:RX 7900、FSR 2真是绝配!光追游戏爽翻天
- 影驰PCIe 5.0 SSD温度实测:小风扇立功了
- 张本智和丢冠原因揭晓!超级黑马崛起,表态要在世乒赛拿男单奖牌 最新资讯
- 全球快资讯:格林伍德即将回归顶级联赛,尤文有望签曼联弃将,博格巴成中间人
- 环球焦点!【全球新视野】今日热议:焦点快播:海通证券:货币紧缩政策边际放缓 贵金属有望迎来板块性投资机会 每日热门_焦点滚动_天天新要闻
- AMD为ROG掌机定制Zen4+RDNA3神U:功耗只有9W!|环球百事通
- 【聚看点】华为严打App互相拉起!不整改者直接下线、上报工信部
- 第一次!嫦娥五号发现月球天然玻璃:建基地的好材料-天天热头条
- 特斯拉中国五一出行报告:百位车友日行千里 没有里程焦虑 天天快报
- 去哪里?阿斯报:布斯克茨预计在巴萨夺冠后宣布自己的未来-世界讯息
- 美国统治全球48%半导体市场:研发投入占比2.5倍于中国
- 通讯!宝德暴芯x86处理器发布:百分百复刻Intel 10代酷睿
- 贾跃亭没忘记乐视!时隔6年 首次互动|环球微资讯
- 世界杯预选赛欧洲区第三轮德国主场被爆冷 当前快报
- 男子1天吃10顿暴瘦110斤:确诊为甲亢!医生科普
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
焦点速讯:86.返回类型和return语句
return 语句终止当前比在执行的函数并将控制权返回到调用该函数的地方。 return语句有两种形式:
(相关资料图)
return; return expression;
1.无返回值函数
没有返回值的 return 语句只能用在返回类型是 void 的函数中。返回 void 的函数不要求非得有 return 语句,因为在这类函数的最后一句后面会隐式地执行 return。 通常悄况下,void 函数如果想在它的中间位置提前退出, 可以使用 return 语句。return 的这种用法有点类似于我们用 break 语句(参见5.5.1节,第170页)退出循环。 例如,可以编写一个 swap 函数,使其在参与交换的值相等时什么也不做直接退出:
void swap(int &v1, int &v2) { //如果两个值是相等的,则不需要交换,直接退出 if(v1 == v2) return; //如果程序执行到了这里,说明还需要继续完成某些功能 int tmp = v2; v2 = v1; v1 = tmp; //此处无须显式的return语句}
这个函数首先检查值是否相等,如果相等直接退出函数;如果不相等才交换它们的值。在最后一条赋值语句后面隐式地执行 return。
一个返回类型是void的函数也能使用return语句的第二种形式,不过此时return语句的 expression 必须是另一个返回 void 的函数。强行令void函数返回其他类型的表达式将产生编译错误。
2.有返回值函数
return语句的第二种形式提供了函数的结果。 只要函数的返回类型不是void,则该函数内的每条return语句必须返回一个值。return 语句返回值的类型必须与函数的返同类型相同,或者能隐式地转换成(参见4.11节, 第141页)函数的返回类型。
尽管C++无法确保结果的正确性,但是可以保证每个return 语句的结果类型正确。
也许无法顾及所有情况,但是编译器仍然尽量确保具有返回值的函数只能通过return 语句退出。例如:
//因为含有不正确的返回值,所以这段代码无法通过纸译bool str_subrange(const string &str1, const string &str2) { //大小相同:此时用普通的相等性判断结果作为返回值 if (str1.size() == str2.size()) return str1 == str2;//正确:==运算符返回布尔值 //得到较短 string对象的大小,条件运算符参见第4.7节 (134 页) auto size = (str1.size() < str2.size()) ? strl. size () : str2. size() ; //检查两个 string对象的对应字符是否相等,以较短的字符串长度为限 for(decltype(size) i = O; i != size; ++i) { if (str1[i] != str2[i]) return;//错误#1: 没有返回值,编译器将报告这一错误 } //错误#2:控制流可能尚未返回任何值就结束了函数的执行 //编译器可能检查不出这一错误}
for循环内的return语句是错误的,因为它没有返回值,编译器能检测到这个错误。
第二个错误是函数在for循环之后没有提供return语句。在上面的程序中,如果一个string对象是另一个的子集,则函数在执行完for循环后还将继续其执行过程,显然应该有一条return语句专门处理这种情况。编译器也许能检测到这个错误,也许不能;如果编译器没有发现这个错误,则运行时的行为将是未定义的。
在含有return语句的循环后面应该也有一条return语句,如果没有的话该程序就是错误的。很多编译器都无法发现此类错误。
2.1值是如何被返回的
返回一个值的方式和初始化一个变量或形参的方式完全一样:返回的值用于初始化调用点的一个临时量,该临时量就是函数调用的结果。
必须注意当函数返回局部变量时的初始化规则。例如我们书写一个函数,给定计数值、单词和结束符之后,判断计数值是否大于1:如果是,返回单词的复数形式;如果不是,返回单词原形:
//如果ctr的值大于1,返回word的复数形式string make_plural(size_t ctr, const string &word, const string &ending) { return (ctr > 1) ? word + ending : word;}
该函数的返回类型是string,意味着返同值将被拷贝到调用点。因此,该函数将返回word的副本或者一个未命名的临时string对象, 该对象的内容是word和ending的和。
同其他引用类型一样,如果函数返回引用,则该引用仅是它所引对象的一个别名。举个例子来说明,假定某函数挑出两个string形参中较短的那个并返回其引用:
//挑出两个string对象中较短的那个,返回其引用const string &shorterString(const string &s1, const string &s2){ return s1.size() <= s2.size() ? s1 : s2; }
其中形参和返回类型都是const s七ring的引用, 不管是调用函数还是返回结果都不会<豆句 真正拷贝s七ring对象。
2.2不要返回局部对象的引用或指针
函数完成后,它所占用的存储空间也随之被释放掉(参见6.1.1节, 笫184页)。囚此,函数终止意味着局部变量的引用将指向不再有效的内存区域:
//严重错误:这个函数试图返回局部对象的引用 const string &manip () { string ret; //以某种方式改变一下ret if (!ret.empty()) return ret;//错误:返回局部对象的引用! else return "Empty";//错误:"Empty",是一个局部临时量}
上面的两条return语句都将返回未定义的值,也就是说,试图使用manip函数的返同值将引发未定义的行为。对于第一条return语句来说,显然它返回的是局部对象的引用。在第二条return语句中,字符串字面值转换成一个局部临时string对象,对于manip来说,该对象和ret样都是局部的。当函数结束时临时对象占用的空间也就随之释放掉了,所以两条return语句都指向了不再可用的内存空间。
建议:
要想确保返回值安全,我们不妨提问:引用所引的是在函数之前已经存在的哪个对象?
如前所述,返回局部对象的引用是错误的;同样,返回局部对象的指针也是错误的。一旦函数完成,局部对象被释放,指针将指向一个不存在的对象。
2.3返回类类型的函数和调用运算符
和其他运算符一样,调用运算符也有优先级和结合律(参见4.1.2节,第121页)。调用运算符的优先级与点运符和箭头运算符(参见4.6节,第133页)相同,并且也符合左结合律。因此,如果函数返回指针、引用或类的对象,我们就能使用函数调用的结果访问结果对象的成员。
例如,我们可以通过如下形式得到较短string对象的长度:
//调用string对象的size成员,该string对象是由shorter String函数返回的auto sz = shorterString(s1, s2).size();
因为上面提到的运算符都满足左结合律,所以shorterString的结果是点运算符的左侧运符对象,点运算符可以得到该string对象的size成员,size又是第二个调用运算符的左侧运算对象。
2.4引用返回左值
函数的返同类型决定函数调用是否是左值(参见4.1.1节,第121页)。调用 一个返同引用的函数得到左值,其他返回类型得到右值。可以像使用其他左值那样来使用返回引用的函数的调用,特别是,我们能为返回类型是非常量引用的函数的结果赋值:
char &get_val(string &str, string::size_type ix) { return str[ix];//get_val假定索引值是有效的}int main() { string s("a value"); cout << s << endl;//输出a value get_val(s, 0) = "A";//将s[0]的值改为 A cout << s << endl;//输出A value return 0;}
把函数调用放在赋值语句的左侧可能看起来有点奇怪,但其实这没什么特别的。返同伯丛引用,因此调用是个左值,和其他左值一样它也能出现在赋值运算符的片侧。
如果返回类型是常量引用,我们不能给调用的结果赋值,这一点和我们熟悉的情况一样的:
shorter String("hi","bye")= "X";//错误:返回值是个常量
2.5列表初始化返回值
C++11新标准规定,函数可以返回花括号包围的值的列表。类似其他返回结果,此处的列表也用来对表示函数返回的临时量进行初始化。如果列表为空,临时量执行值初始化(参见3.3.1节,第88页):否则,返回的值由函数的返回类型决定。
举个例子,回忆6.2.6节(第198页)的error_msg函数,该函数的输入是一组可变数量的string实参,输出由这些string对象组成的错误信息。在下面的函数中,返回一个vector对象,用它存放表示错误信息的string对象:
vector process() { //... //expected和actual是string对象 if (expected.empty ()) return{};//返回一个空vector对象 else if (expected== actual) return {"functionX", "okay"};//返回列表初始化的vector对象 else return{"functionX", expected, actual}; }
第一条return语句返回一个空列表,此时,process函数返回的vector对象是空的。如果expected不为空,根据expected和actual是否相等,函数返回的vector对象分别用两个或三个元素初始化。 如果函数返回的是内置类型,则花括号包围的列表最多包含一个值,而且该值所占空间不应该大于目标类型的空间(参见2.2.1节,第39贞)。如果函数返回的是类类型,由类本身定义初始值如何使用(参见3.3.1节,第89页)。12
2.6主函数main的返回值
之前介绍过,如果函数的返回类型不是void,那么它必须返回一个值。但是这条规则有个例外:我们允许main函数没有return语句直接结束。如果控制到达了main函数的结尾处而且没有return语句,编译器将隐式地插入一条返回0的return语句。 如1.1节(第2页)介绍的,main函数的返回值可以看做是状态指示器。返回0表示执行成功,返回其他值表示执行失败,其中非0值的具体含义依机器而定。为了使返回值与机器无关,cstdlib头文件定义了两个须处即变量(参见2.3.2节,第49页),我们可以使用这两个变量分别表示成功与失败:
int main(){ if (some_failure) return EXIT_FAILURE;//定义在cstdlib头文件中 else return EXIT_SUCCESS;//定义在cstdlib头文件中}
因为它们是预处理变量,所以既不能在前面加上std::,也不能在using声明中出现。
2.7递归
如果一个函数调用了它自身,不管这种调用是直接的还是间接的,都称该函数为递归函数(recursive function)。举个例子,我们可以使用递归函数重新实现求阶乘的功能:
//计算val的阶乘,即1 * 2 * 3... * valval int factorial(int val){ if (val > 1) return factorial(val - 1) * val; return 1; }
在上面的代码中,我们递归地调用factorial函数以求得从val中减去1后新数字的阶乘。 当val递减到1时,递归终止,返回1。
在递归函数中,一定有某条路径是不包含递归调用的;否则,函数将 “永远”递归下去,换句话说,函数将不断地调用它自身直到程序栈空间耗尽为止。我们有时候会说这种函数含有递归循环(recursion loop)。在factorial函数中,递归终止的条件是val等于1。
下面的表格显示了当给factorial函数传入参数5时,函数的执行轨迹。
调用 | factoriaI (5)的执行轨迹 返回 | 值 |
---|---|---|
factorial(5) | factorial(4)* 5 | 120 |
factorial(4) | factorial(3)* 4 | 24 |
factorial(3) | factorial(2)* 3 | 6 |
factorial(2) | factorial(1)* 2 | 2 |
factorial(1) | 1 | 1 |
注意:
main函数不能调用它自己。
3.返回数组指针
因为数组不能被拷贝,所以函数不能返回数组。不过,函数可以返回数组的指针或引用(参见3.5.1节,第102页)。虽然从语法上来说,要想定义一个返回数组的指针或引用一些方法可以简化这一的函数比较烦琐,但是有任务,其中最直接的方法是使用类型别名(参见2.5.1节,第60页):
typedef int arrT[10];//arrT是一个类型别名,它表示的类型是含有10个整数的数组using arrT = int[10];//arrT的等价声明,参见2.5.1节(第60页)arrT* func(int i);//func返回一个指向含有10个整数的数组的指针
其中arrT是含有10个整数的数组的别名。因为我们无法返回数组,所以将返同类型定义成数组的指针。因此,func函数接受一个int实参,返同一个指向包含10个整数的数组的指针。
3.1声明一个返回数组指针的函数
要想在声明func时不使用类型别名,我们必须牢记被定义的名字后面数组的维度:
int arr[10]; int *p1[10]; int (*p2)[10]= &arr;
和这些声明一样,如果我们想定义一个返回数组指针的函数,则数组的维度必须跟在函数名字之后。然而,函数的形参列表也跟在函数名字后面且形参列表应该先于数组的维度。因此,返回数组指针的函数形式如下所示:
Type (*function(parameter_list))[dimension]
类似于其他数组的声明,Type表示元素的类型,dimension表示数组的大小。 (*function(parameter_list))两端的括号必须存在,就像我们定义p2时两端必须有括号一样。如果没有这对括号,函数的返回类型将是指针的数组。
举个具体点的例子,下面这个func函数的声明没有使用类型别名:
int(*func(inti))[10];
可以按照以下的顺序来逐层理解该声明的含义:
●func(int i)表示调用func函数时需要
●(*func(int i))意味着我们可以对函数调用的结果执行解引用操作。●(*func (int i)) [10]表示解引用func的调用将得到一个大小是10的数组。
●int (*func (int i)) [10]表示数组中的元素是int类型。
3.2使用尾置返回类型
在C++11新标准中还有一种可以简化上述func声明的方法,就是使用尾置返回类型 (trail return type)。 任何函数的定义都能仗用尾置返回, 但是这种形式对于返回类型比较复杂的函数最有效,比如返回类型是数组的指针或者数组的引用。尾置返回类型跟在形参列表后面并以个->符号开头。为了表示函数真正的返回类型跟在形参列表之后,我们在本应该出现返回类型的地方放置一个auto:
//func接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组auto func(int i) -> int(*) [10];
因为我们把函数的返回类型放在了形参列表之后,所以可以清楚地看到func函数返回的是一个指针,并且该指针指向了含有10个整数的数组。
3.3使用 decltype
还有一种情况,如果找们知道函数返回的指针将指向哪个数组,就可以使用decltype关键字声明返回类型。 例如, 下面的函数返回一个指针, 该指针根据参数i的不同指向两个已知数组中的某一个:
int odd[] = { 1, 3, 5, 7, 9 };int even[] = {0, 2, 4, 6, 8}; //返回一个指针,该指针指向含有5个整数的数组decltype(odd) *arrPtr(int i) { return (i % 2) ? &odd : &even;//返回一个指向数组的指针}
arrPtr使用关键字decltype表示它的返回类型是个指针,并且该指针所指的对象与odd的类型一致。因为odd是数组,所以arrPtr返回一个指向含有5个整数的数组的指针。 有一个地方需要注意:decltype并不负责把数组类型转换成对应的指针,所以decltype的结果是个数组,要想表示arrPtr返回指针还必须在函数声明时加一个*号。参考资料:
C++ Primer
关键词:
焦点速讯:86.返回类型和return语句
用CPU来加速你的Linux命令 消息
最新消息:零余额账户是什么意思_零余额帐户是什么意思啊
天天讯息:AMD:RX 7900、FSR 2真是绝配!光追游戏爽翻天
影驰PCIe 5.0 SSD温度实测:小风扇立功了
张本智和丢冠原因揭晓!超级黑马崛起,表态要在世乒赛拿男单奖牌 最新资讯
全球快资讯:格林伍德即将回归顶级联赛,尤文有望签曼联弃将,博格巴成中间人
ASP.NET Core MVC 从入门到精通之序列化
网络基础 CAS协议学习总结_天天新资讯
环球观点:Git使用经验总结1
环球焦点!【全球新视野】今日热议:焦点快播:海通证券:货币紧缩政策边际放缓 贵金属有望迎来板块性投资机会 每日热门_焦点滚动_天天新要闻
AMD为ROG掌机定制Zen4+RDNA3神U:功耗只有9W!|环球百事通
【聚看点】华为严打App互相拉起!不整改者直接下线、上报工信部
第一次!嫦娥五号发现月球天然玻璃:建基地的好材料-天天热头条
特斯拉中国五一出行报告:百位车友日行千里 没有里程焦虑 天天快报
去哪里?阿斯报:布斯克茨预计在巴萨夺冠后宣布自己的未来-世界讯息
送电子书福利啦!|每日关注
美国统治全球48%半导体市场:研发投入占比2.5倍于中国
通讯!宝德暴芯x86处理器发布:百分百复刻Intel 10代酷睿
贾跃亭没忘记乐视!时隔6年 首次互动|环球微资讯
世界杯预选赛欧洲区第三轮德国主场被爆冷 当前快报
.NET 6学习笔记(8)生成自签证书
男子1天吃10顿暴瘦110斤:确诊为甲亢!医生科普
每日快看:董宇辉自曝曾抗拒卖货写检讨:一度撑不下去想放弃
每日信息:银河麒麟桌面系统升级V10 SP1 2303:固若金汤 真心好用!
当前视点!巴萨唯一爆点要走,5000万欧元违约金,让签约不要太容易
全球速讯:海康威视推双盘位NAS:1199元 最大40TB容量
因“挖呀挖”爆火美女老师身陷6大传闻:职业网红?一场直播打赏200多万?-天天要闻
三国志战略版象兵战法怎么样 三国志战略版象兵战法搭配
挂载NTFS分区,离线安装NTFS-3G(Linux挂载NTFS格式磁盘的方法)
《塞尔达传说:王国之泪》偷跑后:任天堂大规模“清理”Switch相关软件
腾势汽车五一出行报告:座椅零重力成最爱用智能功能 被使用84万次-世界最资讯
世界新动态:葱花饼怎样做好吃?
“秀色”可餐鲜花入馔有讲究 谨防过敏或中毒_每日快播
环球速看:治堵神器!比亚迪云巴在湖南大王山即将运营:串联十余处景点
广东强对流天气上线 多地暴雨大风:汕尾3小时倒水111.1毫米|世界微动态
对标华为昆仑!荣耀将推出巨犀玻璃面板:Magic4已提前用上
创维汽车黄宏生:盈亏平衡点是卖10万辆 明年实现
收购动视暴雪还有机会!微软聘请顶级反垄断律师对阵CMA 全球今头条
全球今头条!称比亚迪仰望U8原地掉头是欺骗大众 38万粉丝UP主道歉
1163 Dijkstra Sequence + 层序遍历 + 链式前向星_环球热点
马普龙霸王龙谁厉害_马普龙vs霸王龙 今日播报
《塞尔达传说:王国之泪》发售前惨遭偷跑!Epic:买不起可以玩《原神》
【天天时快讯】超越《复联》!《银河护卫队3》创漫威影史最高分
桥本环奈的影视剧_桥本环奈影视作品 焦点热闻
全球最新:女子深夜加班回家吃榴莲被丈夫指责 网友质疑摆拍:头顶长了摄像头
巴菲特看好微软:在收购动视暴雪上已经十分出色|全球信息
动态:又一新造车濒临倒闭:仅交付6台车 和富士康有关
全球今亮点!又一新势力车企申请破产 经销商曾集体维权称被坑几百万
近日择机发射!天舟六号船箭组合体转运至发射区_世界播资讯
这几类蔬菜或自带“毒素”,吃前必须焯水,有两种正当季-今日报
每日动态!【金融街发布】国家外汇管理局:4月末我国外储规模为32048亿美元 环比上升0.66%
【环球新要闻】国王杯冠军榜:巴萨31冠居首,皇马20冠排第三
世界动态:上海官方公布4月超速排行榜:第一名真能追高铁了 一秒67米
回忆杀!“品如的苹果手机怎么是翻盖的”引热议 网友又来考古
Linux驱动开发笔记(一):helloworld驱动源码编写、makefile编写以及驱动编译基本流程 当前速讯
视讯!OpenAI CLIP 关键点 - 连接图像和文字
宁德时代回应原材料价格下跌:不存在大幅减值风险
把苹果股票卖了!巴菲特:两年前犯过错 很愚蠢|世界快看
理想汽车:几万块营销预算李想亲自批 但安全方面预算不需要
关于Kubernetes-v1.23.6-初始化时报错[kubelet-check] It seems like the kubelet isn't runni
编程题库 - 基本运算 - 整数运算求两个整数相加之和
零营收药企密集IPO 估值成关注点
天天看点:iPhone 15 Pro Max机模上手:1.57mm超窄边框、Type-C接口
对于女大学生 一晚上最少多少钱
一夜爆红 湖北黄老师直播唱挖呀挖打赏不断 律师:或涉嫌侵权
每日关注!夏天必备 润本蚊香液3瓶+1器大促:到手14.9元
254TOPS算力!比亚迪新一代王朝、海洋系列要用NVIDIA Drive Orin芯片-天天快报
前沿热点:Win11精简版系统成功安装在4GB显存中:运行速度飞快!
微头条丨炉慈高速全线首座隧道双线提前贯通
【环球时快讯】侵害用户权益!工信部通报56款App:羊了个羊上榜
焦点快报!巴菲特股东大会!巴菲特:我们的火车还停留在19世纪末水平
学系统集成项目管理工程师(中项)系列18b_进度管理(下)-当前动态
世界快报:关于俞敏洪建议24节气都放假及俞敏洪建议24节气都放假详情
2、etcd单机部署和集群部署
网友逛鱼店惊喜偶遇鲨鱼产子过程:第一次见 很神奇
深圳一公司发布年薪50万岗位:优先录用李一桐粉丝
7人吃自助炫300多个螃蟹 医生:过量食用螃蟹或引发多种疾病|世界时讯
苹果别对iPhone 15 USB-C限速!不然欧盟不答应
加快摆脱中国供应链?库克:苹果接下来就靠印度了
什么是成本性态 什么是成本|世界热讯
爱成都迎大运宣传稿怎么画(爱成都迎大运宣传句)
咖啡色地板配什么颜色家具_咖啡色配什么颜色好看
网站被攻击了!!! 速递
老人推倒摩托车案执行款1.6万已到账 车主10个月维权结束:老人违法不该被宽恕
天天百事通!民呼我应|东门一市政路被“霸占”,官方回应来了
【环球新要闻】月嫂拍嗝时打盹致婴儿头顶骨骨折 平台:愿退还未完成的服务费
“挖呀挖呀挖”童谣为何火爆全网?专家解释原因_天天速看
全球今日报丨冷冻小龙虾怎么加热 冷冻小龙虾怎么加热才好吃
美股银行股周五为何大涨?没有空头想持仓过周末
天天速讯:中国特供 NVIDIA缩水版A800显卡遭哄抢:10万元也难买到
“投资界的春晚”要来了:巴菲特股东大会五大看点_世界微动态
老黄良心了 5000块的4060游戏本值得买吗?结论来了
复数的基本知识
最新快讯!关于学生五一前请假遭拒强行离校被处分及学生五一前请假遭拒强行离校被处分详情
广东小区业主私拆承重墙 多户搬离墙体开裂到14楼:网友吐槽是谋杀 希望严惩
5月价格继续涨 LCD面板不再亏本卖:75寸电视不到3000元
快播:“土味”出圈!济宁“90后”唢呐女博士背后的故事
最新消息:SQL 解析在 CloudQuery 中的应用
小红书布局AI大模型:上线AI绘画应用