函数的返回值是如何带出和接收的以及内存中的活动情况.RP
函数返回值时,要生成一个值的副本。
而用引用返回值时,不生成值的副本。
例如,下面的程序是有关引用返回的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的更多相关文章
- C语言中函数的返回值
规则 除局部变量的内存地址不能作为函数的返回值外,其他类型的局部变量都能作为函数的返回值. 我总结出下面这些规则: int.char等数据类型的局部变量可以作为函数返回值. 在函数中声明的指针可以作为 ...
- c++特性:指向类成员的指针和非类型类模板参数和函数指针返回值 参数推导机制和关联型别
一.c++允许定义指向类成员的指针,包括类函数成员指针和类数据成员指针 格式如下: class A { public: void func(){printf("This is a funct ...
- Python的函数式编程-传入函数、排序算法、函数作为返回值、匿名函数、偏函数、装饰器
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. ...
- Flask实战第6天:视图函数Response返回值
视图函数的返回值会被自动转换为一个响应对象,Flask的转换逻辑如下: 如果返回的是一个合法的响应对象,则直接返回 可以使用make_response函数来创建Response对象,这个方法可以设置额 ...
- python -- 初始函数 函数的定义,函数的返回值以及函数的参数
1.什么是函数,函数的定义及语法 2.函数的返回值 3.函数的参数 一.函数的定义及语法 函数的定义:定义了一个动作或者功能,是对功能的封装 语法: def 函数名( 形参列表 ): ...
- 获取JavaScript异步函数的返回值
今天研究一个小问题: 怎么拿到JavaScript异步函数的返回值? 1.错误尝试 当年未入行时,我的最初尝试: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <s ...
- 6.1 函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数
函数的返回值: 函数一旦执行到 return,函数就会结束,并会返回return 后面的值,如果不使用显式使用return返回,会默认返回None . return None可以简写为 r ...
- Swift2.0语言教程之函数的返回值与函数类型
Swift2.0语言教程之函数的返回值与函数类型 Swift2.0中函数的返回值 根据是否具有返回值,函数可以分为无返回值函数和有返回值函数.以下将会对这两种函数类型进行讲解. Swift2.0中具有 ...
- C++函数的返回值——返回引用类型&非引用类型
函数的返回主要分为以下几种情况: 1.主函数main的返回值: 允许主函数main没有返回值就可结束:可将主函数main返回的值视为状态指示器,返回0表示程序运行成功,其他大部分返回值则表示失败. 2 ...
随机推荐
- C语言编译全过程
编译的概念:编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序. ...
- 学习动态性能表(22)V$resource_limit
学习动态性能表 第20篇--V$resource_limit 2007.6.15 就一条SQL语句供你参考: select * from V$RESOURCE_LIMIT where resourc ...
- java编程思想第九章接口
9.1抽象类和抽象方法 为什么要有抽象类? 是希望通过通用接口操作一系列类. 那么抽象类的形式是什么样的呢? 声明类的使用使用abstract关键字,且在该类中应该具有抽象方法. 注:抽象方法被关键字 ...
- GXT4.0 BorderLayoutContainer布局
T字型布局. @Override public void onModuleLoad() { BorderLayoutContainer con = new BorderLayoutContainer( ...
- ucos ii 百度官方介绍
μC/OS II(Micro-Controller Operating System Two)是一个可以基于ROM运行的.可裁剪的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处 ...
- C语言库在不同系统下的后缀
C语言的静态库与动态库对比分析,各有长短 库: 指由标准常用函数编译而成的文件,旨在提高常用函数的可重用性,减轻开发人员负担.常用的sdtio.h,math.h等 库 ...
- Redis 复制技术和高可用sentinel(哨兵模式)
redis的复制技术和高可用(哨兵模式) 1 复制 为什么要复制 实现数据的多副本存储,从而可以实现服务的高可用 提供更好的读性能复制技术的关键点及难点 如何指定被复制对象 增量还是全量以及如何实现增 ...
- SQL基础(1)
1.SQL简介 (1)什么是SQL? SQL指结构化查询语言 SQL使我们有能力访问数据库 SQL是一种 ANSI 的标准计算机语言 (2)SQL 能做什么? SQL面向数据库执行查询 SQL可从数据 ...
- ie6 ie7下报脚本错误"Expected identifier, string or number" 的原因和解决方法
在IE6和ie7里面,脚本报错"Expected identifier, string or number" 写下这个是个之前我已经很头疼了,因为我的代码在其他浏览器里都是正常的, ...
- 10-21C#基础--集合
二.集合 //定义一个集合,集合是一个类, 1. 定义: ArrayList al = new ArrayList(); 2.添加数据:al.add();//添加数值,可以添加无数个元素,集合中没有 ...