函数返回值时,要生成一个值的副本。

而用引用返回值时,不生成值的副本。

  例如,下面的程序是有关引用返回的4种形式:
    //*********************
    //**   ch9_6.cpp  **
    //*********************

    #include <iostream.h>

    float temp;

    float fn1(float r)
    {
     temp = r*r*3.14;
     return temp;
    }

    float& fn2(float r)
    {
     temp = r*r*3.14;
     return temp;
    }

    void main()
    {
     float a=fn1(5.0); //1
     float& b=fn1(5.0); //2:warning
     float c=fn2(5.0); //3
     float& d=fn2(5.0); //4
     cout<<a<<endl;
     cout<<b<<endl;
     cout<<c<<endl;
     cout<<d<<endl;
    }

  运行结果为:
    78.5
    78.5
    78.5
    78.5

  对主函数的4种引用返回的形式, 程序的运行结果是一样的。但是它们在内存中的活动情况是各不相同的。其中变量temp是全局数据,驻留在全局数据区data。函数main()、函数fnl()或函数fn2()驻留在栈区stack。

  第一种情况:见图9-5。


图9-5 返回值方式的内存布局

  这种情况是一般的函数返回值方式。 返回全局变量temp值时,C++创建临时变量并将temp的值78.5复制给该临时变量。返回到主函数后,赋值语句a=fnl(5.0)把临时变量的值78.5复制给a。

第二种情况:见图9-6。


图9-6 返回值初始引用的情形

  这种情况下,函数fnl()是以值方式返回的,返回时, 复制temp的值给临时变量。返回到主函数后,引用b以该临时变量来初始化,使得b成为该临时变量的别名。由于临时变量的作用域短暂,所以b面临无效的危险。 根据C++标准,临时变量或对象的生命期在一个 完整的语句表达式结束后便宣告结束,也即在“float& b=fnl(5.0);”之后,临时变量不再存在。 所以引用b以后的值是个无法确定的值。BC对C++标准进行了扩展,规定如果临时变量或对象作为引用的初始化时,则其生命期与该引用一致。14.7节将进一步介绍这一内容。 这样的程序, 依赖于编译器的具体实现,所以移植性是差的。
  若要以返回值初始化一个引用,应该先创建一个变量,将函数返回值赋给这个变量,然 后再以该变量来初始化引用,就像下面这样:
    int x=fnl(5.0);
    int& b=x;

  第三种情况:见图9-7。


图9—7 返回引用方式

  这种情况,函数fn2()的返回值不产生副本,所以, 直接将变量temp返回给主函数。主函数的赋值语句中的左值,直接从变量temp中得到复制,这样避免了临时变量的产生。当变量temp是一个用户自定义的类型时,这种方式直接带来了程序执行效率和空间利用的利益。

第四种情况:见图9-8。


图9—8 返回引用方式的值作为引用的初始化

  这种情况, 函数fn2()返回一个引用,因此不产生任何返回值的副本。在主函数中,一个引用声明d用该返回值来初始化,使得d成为temp的别名。由于temp是全局变量, 所以在d的有效期内temp始终保持有效。这样做法是安全的。

P.S.

但是, 如果返回不在作用域范围内的变量或对象的引用, 那就有问题了。这与返回一个局部作用域指针的性质一样严重。BC作为编译错误,VC作为警告,来提请编程者注意。例如,下面的代码返回一个引用,来给主函数的引用声明初始化:
    float& fn2(float r)
    {
     float temp;
     temp=r*r*3.14;
     return temp;
    }
    void main()
    {
     float &d=fn2(5.0); //error返回的引用是个局部变量
    }

  见图9-9说明。


图9-9 返回的引用是局部变量

  如果返回的引用是作为一个左值进行运算,也是程序员最犯忌的。所以,如果程序中有下面的代码,则一定要剔除:
    float& fn2(float r)
    {
     float temp;
     temp=r*r*3.14;
     return temp;
    }
    void main()
    {
     fn2(5.0)=12.4; //error返回的是局部作用域内的变量
    }

文自:http://blog.csdn.net/tcdddd/article/details/5519332

函数的返回值是如何带出和接收的以及内存中的活动情况.RP的更多相关文章

  1. C语言中函数的返回值

    规则 除局部变量的内存地址不能作为函数的返回值外,其他类型的局部变量都能作为函数的返回值. 我总结出下面这些规则: int.char等数据类型的局部变量可以作为函数返回值. 在函数中声明的指针可以作为 ...

  2. c++特性:指向类成员的指针和非类型类模板参数和函数指针返回值 参数推导机制和关联型别

    一.c++允许定义指向类成员的指针,包括类函数成员指针和类数据成员指针 格式如下: class A { public: void func(){printf("This is a funct ...

  3. Python的函数式编程-传入函数、排序算法、函数作为返回值、匿名函数、偏函数、装饰器

    函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. ...

  4. Flask实战第6天:视图函数Response返回值

    视图函数的返回值会被自动转换为一个响应对象,Flask的转换逻辑如下: 如果返回的是一个合法的响应对象,则直接返回 可以使用make_response函数来创建Response对象,这个方法可以设置额 ...

  5. python -- 初始函数 函数的定义,函数的返回值以及函数的参数

    1.什么是函数,函数的定义及语法 2.函数的返回值 3.函数的参数 一.函数的定义及语法 函数的定义:定义了一个动作或者功能,是对功能的封装 语法: def 函数名( 形参列表 ):          ...

  6. 获取JavaScript异步函数的返回值

    今天研究一个小问题: 怎么拿到JavaScript异步函数的返回值? 1.错误尝试 当年未入行时,我的最初尝试: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <s ...

  7. 6.1 函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数

      函数的返回值: 函数一旦执行到   return,函数就会结束,并会返回return 后面的值,如果不使用显式使用return返回,会默认返回None . return None可以简写为   r ...

  8. Swift2.0语言教程之函数的返回值与函数类型

    Swift2.0语言教程之函数的返回值与函数类型 Swift2.0中函数的返回值 根据是否具有返回值,函数可以分为无返回值函数和有返回值函数.以下将会对这两种函数类型进行讲解. Swift2.0中具有 ...

  9. C++函数的返回值——返回引用类型&非引用类型

    函数的返回主要分为以下几种情况: 1.主函数main的返回值: 允许主函数main没有返回值就可结束:可将主函数main返回的值视为状态指示器,返回0表示程序运行成功,其他大部分返回值则表示失败. 2 ...

随机推荐

  1. [转]C++ 智能指针详解

    转自:http://blog.csdn.net/xt_xiaotian/article/details/5714477 C++ 智能指针详解 一.简介 由于 C++ 语言没有自动内存回收机制,程序员每 ...

  2. Linux命令学习(17):ifconfig命令

    版权声明更新:2017-05-22博主:LuckyAlan联系:liuwenvip163@163.com声明:吃水不忘挖井人,转载请注明出处! 1 文章介绍 我们知道,在windows中,除了在图形界 ...

  3. hw_module_t 加载过程

    每一个HAL模块都有一个ID值,以这些ID值为参数来调用硬件抽象层提供的函数hw_get_module就可以将指定的模块加载到内存来,并且获得 一个hw_module_t接口来打开相应的设备. 函数h ...

  4. UDP打洞原理及代码

    来源:http://www.fenbi360.net/Content.aspx?id=1021&t=jc UDP"打洞"原理 1.       NAT分类 根据Stun协议 ...

  5. [转]NME Android目标中文输入问题完美解决!

    最近研究了一下haxe,发现蛮牛逼的,转几篇知识帖 haXe开发笔记:中文问题的小结 * .hx源文件中如果包含中文,要保存成UTF-8编码才能够正确被haXe编译器解析,是否包含BOM(Byte O ...

  6. debian7.2+nginx+mysql

    1.安装mysql sudo aptitude install mysql-server netstat -atln 查看3306端口 数据库目录: /var/lib/mysql/ 配置文件/usr/ ...

  7. Kosaraju

    https://www.cnblogs.com/nullzx/p/6437926.html

  8. vijos1264:神秘的咒语

    描述 身为拜月教的高级间谍,你的任务总是逼迫你出生入死.比如这一次,拜月教主就派你跟踪赵灵儿一行,潜入试炼窟底. 据说试炼窟底藏着五行法术的最高法术:风神,雷神,雪妖,火神,山神的咒语.为了习得这些法 ...

  9. centos7下搭建ceph luminous(12.2.1)--无网或网络较差

    本博客的主要内容是在centos7下搭建luminous,配置dashboard,搭建客户端使用rbd,源码安装ceph,最后给出一些较为常用的命令.本博客针对初次接触ceph的人群. 搭建环境: 主 ...

  10. UTF-8, Unicode, GB2312格式串转换之C语言版

    原住址:http://www.cnitblog.com/wujian-IT/archive/2007/12/13/37671.html           /*      author:   wu.j ...