C/C++ 引用作为函数的返回值

C/C++ 引用作为函数的返回值语法 类型 amp 函数名 形参列表 函数体 特别注意 1 引用作为函数的返回值时 必须在定义函数时在函数名前将 amp 2 用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本 代码来源 RUNOOB include lt iostream gt usingnamespa floattemp floatfn1 floatr

语法:类型 &函数名(形参列表){ 函数体 }

特别注意:

1.引用作为函数的返回值时,必须在定义函数时在函数名前将&

2.用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本

//代码来源:RUNOOB #include 
  
    using namespace std; float temp; float fn1(float r){ temp=r*r*3.14; return temp; } float &fn2(float r){ //&说明返回的是temp的引用,换句话说就是返回temp本身 temp=r*r*3.14; return temp; } int main(){ float a=fn1(5.0); //case 1:返回值 //float &b=fn1(5.0); //case 2:用函数的返回值作为引用的初始化值 [Error] invalid initialization of non-const reference of type 'float&' from an rvalue of type 'float' //(有些编译器可以成功编译该语句,但会给出一个warning) float c=fn2(5.0);//case 3:返回引用 float &d=fn2(5.0);//case 4:用函数返回的引用作为新引用的初始化值 cout< 
    
  

case 1:用返回值方式调用函数(如下图,图片来源:伯乐在线):

C/C++ 引用作为函数的返回值

返回全局变量temp的值时,C++会在内存中创建临时变量并将temp的值拷贝给该临时变量。当返回到主函数main后,赋值语句a=fn1(5.0)会把临时变量的值再拷贝给变量a

case 2:用函数的返回值初始化引用的方式调用函数(如下图,图片来源:伯乐在线)

C/C++ 引用作为函数的返回值

这种情况下,函数fn1()是以值方式返回到,返回时,首先拷贝temp的值给临时变量。返回到主函数后,用临时变量来初始化引用变量b,使得b成为该临时变量到的别名。由于临时变量的作用域短暂(在C++标准中,临时变量或对象的生命周期在一个完整的语句表达式结束后便宣告结束,也就是在语句float &b=fn1(5.0);之后) ,所以b面临无效的危险,很有可能以后的值是个无法确定的值。

 如果真的希望用函数的返回值来初始化一个引用,应当先创建一个变量,将函数的返回值赋给这个变量,然后再用该变量来初始化引用:

 int x=fn1(5.0); int &b=x;

 case 3:用返回引用的方式调用函数(如下图,图片来源:伯乐在线)

C/C++ 引用作为函数的返回值

这种情况下,函数fn2()的返回值不产生副本,而是直接将变量temp返回给主函数,即主函数的赋值语句中的左值是直接从变量temp中拷贝而来(也就是说c只是变量temp的一个拷贝而非别名) ,这样就避免了临时变量的产生。尤其当变量temp是一个用户自定义的类的对象时,这样还避免了调用类中的拷贝构造函数在内存中创建临时对象的过程,提高了程序的时间和空间的使用效率。

case 4:用函数返回的引用作为新引用的初始化值的方式来调用函数(如下图,图片来源:伯乐在线)

C/C++ 引用作为函数的返回值

这种情况下,函数fn2()的返回值不产生副本,而是直接将变量temp返回给主函数。在主函数中,一个引用声明d用该返回值初始化,也就是说此时d成为变量temp的别名。由于temp是全局变量,所以在d的有效期内temp始终保持有效,故这种做法是安全的。

3.不能返回局部变量的引用。如上面的例子,如果temp是局部变量,那么它会在函数返回后被销毁,此时对temp的引用就会成为“无所指”的引用,程序会进入未知状态。

4.不能返回函数内部通过new分配的内存的引用。虽然不存在局部变量的被动销毁问题,但如果被返回的函数的引用只是作为一个临时变量出现,而没有将其赋值给一个实际的变量,那么就可能造成这个引用所指向的空间(有new分配)无法释放的情况(由于没有具体的变量名,故无法用delete手动释放该内存),从而造成内存泄漏。因此应当避免这种情况的发生

5当返回类成员的引用时,最好是const引用。这样可以避免在无意的情况下破坏该类的成员。

6.可以用函数返回的引用作为赋值表达式中的左值

#include 
  
    using namespace std; int value[10]; int error=-1; int &func(int n){ if(n>=0&&n<=9) return value[n];//返回的引用所绑定的变量一定是全局变量,不能是函数中定义的局部变量 else return error; } int main(){ func(0)=10; func(4)=12; cout< 
    
  

C/C++ 引用作为函数的返回值

D.用引用实现多态

在C++中,引用是除了指针外另一个可以产生多态效果的手段。也就是说一个基类的引用可以用来绑定其派生类的实例

class Father;//基类(父类) class Son:public Father{.....}//Son是Father的派生类 Son son;//son是类Son的一个实例 Father &ptr=son;//用派生类的对象初始化基类对象的使用

特别注意:

ptr只能用来访问派生类对象中从基类继承下来的成员如果基类(类Father)中定义的有虚函数,那么就可以通过在派生类(类Son)中重写这个虚函数来实现类的多态。

 

 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/198522.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午3:01
下一篇 2026年3月26日 下午3:02


相关推荐

  • NodeJS、NPM安装配置与测试步骤(windows版本)

    NodeJS、NPM安装配置与测试步骤(windows版本)

    2021年10月11日
    49
  • 0xffffffff是多少?

    0xffffffff是多少?(1)正数的补码与原码相同;(2)负数的符号位为1,其余位为该数绝对值的原码按位取反,然后整个数加1,即为其补码。(总的来说:补码=原码取反+1,只不过负数带有符号位需特殊考虑。。。)—————————————————————————————————–

    2022年5月17日
    40
  • LCD12864示例子程序

    LCD12864示例子程序总结一下一些模块常用的子程序相信很多同学和我一样 刚开始的时候可能不太喜欢拿着数据手册去看 然后去写一些子程序 比如说 lcd12864 或者 lcd1602 的一些写命令 写数据 忙检查子程序等等 这里给大家总结一些模块的子程序 大家直接可以复制粘贴拿来用 LCD12864 模块下面是实际使用 lcd12864 模块的子程序 当然如果大家买的模块带中文字库 可以直接查找字库表显示中文汉字 或者直接将中文字符串进行输出显示

    2026年3月26日
    2
  • 吃火锅,秒懂云计算

    吃火锅,秒懂云计算

    2022年4月3日
    42
  • iocomp入门教程(绘制Plot)[通俗易懂]

    iocomp入门教程(绘制Plot)[通俗易懂]最近要做一个项目需要绘制曲线,为了节省时间,就选用了iocomp控件,可网上相关的教程极少,官方给的文档还是比较详尽,但缺少具体的前期准备步骤,在初次接触这个控件很容易蒙,所以我写下这篇,给入门者以便利。用到的材料:iocomp激活成功教程版(目前常见的为V3和V4,两个版本按喜好选择吧~…

    2022年7月25日
    27

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号