C++引用和函数返回值
这是老师上课讲的内容,现在把它写下来,一方面当做复习,另一方面真的想学点东西。废话不多说,先贴上测试的代码:
#include <iostream.h> float temp; float fn1(float r)
{
temp = (float)(r*r*3.14);
return temp;
} float& fn2(float r) //绑定return的变量
{
//float temp; temp = (float)(r*r*3.14);
return temp;
} void main()
{
float a=fn1(5.0); //
float& b=fn1(5.0); //VC++ 6.0 error, (有的编译器warning)
float c=fn2(5.0); //
float& d=fn2(5.0); //如果temp不是全局变量,仍可能有问题
}
在分析上面的代码之前,先说两个理论:
(一)什么是引用。同时借助老师的简单比喻:
一个变量的引用就是这个变量的别名,引用在定义的时候必须同时初始化。老师是这样比喻的,说他有个同学(具体有无此人,无从考证)个子很矮,所以好多人给老段起了个外号叫做根号2,当然了根号2和老段是同一个人,对老段的任何操作都是对根号2的操作。后来又有人给根号2(也就是老段)起了另一个外号叫做矮冬瓜。这样,根号2、老段和矮冬瓜指的就是同一个人了。这里的老段就象征着变量的本体,根号2就是老段的引用,矮冬瓜就是老段的引用的引用。当然了,这三个称谓表示同一个人。
(二)一个函数的声明类型和它具体的返回值类型的关系:
首先知道一点:函数的返回值在内存的栈空间中是要开辟空间的。假设我们给这个空间起个名字叫做END,那么这个END的类型就是函数声明的时候的返回类型,不管你具体实际中返回的是什么类型。例如上面的fn2()函数:
float temp;
float& fn2(float r) //绑定return的变量
{ temp = (float)(r*r*3.14);
return temp;
}
函数返回的时候具体的语法是:float & END = temp;其中float就是这个函数声明时的类型,END就是给函数返回开辟的栈空间,temp就是实际return的东西。这就是用return的temp初始化END引用。这里temp就是老段,END就是根号2。
----------------------------------------------------------------------------------------------------------------------------------------
下面逐个的分析最开始的代码:
(1)
float a = fn1(5.0);
函数返回时的语法为:float END= temp;这样END就是一个float类型的变量。上面的这句代码就是用END这个变量初始化a。随后调用结束,栈空间的END就被os收回了。
(2)
float &b = fn1(5.0);
END为float类型的,函数返回时具体的语法是:float END= temp;这里的END也是一个float类型的变量。上面的这句代码在main函数中给END弄了一个引用(内部用指针实现的)。这里的b是个引用,也就是根号2,END就是老段。但是问题来了,END是暂时的栈空间啊,函数调用结束后它就被清除了啊,相当于在main函数的栈空间中弄了一个指针,但是这个指针指向了一个即将被清除的变量。当然会报错。
(3)
float c = fn2(5.0);
这里的END就是一个引用了,因为fn2声明的时候类型为float &。函数返回时的语法是:float & END = temp;用temp初始化一个引用。这里的END就是根号2,temp就是老段,也就是说对根号2的任何操作都会作用在老段的身上(他们是同一个东西)。所以这个语句的意思就是用temp给c初始化。
(4)
float &d = fn2(5.0);
同样END是引用,这里是用一个引用初始化另一个引用。这时temp是老段,END是根号2,d是矮冬瓜,三个名字说的是同一个人。即使调用结束后,END被清掉了,但是他毕竟是别名,不是变量的本尊,所以不会报错。
-----------------------------------------------------------------------------------------------------------------------------------------
注:作用在引用上的操作,同样会作用在变量本身上,但是如果这个引用的生存期到了,它要消亡了,这是没有关系的。就好像,忽然有一天大家都不在管老段叫根号2,那么根号2这个外号的生存期就到头了。但是这没什么影响。
但是老段不能消亡,你说老段消亡了,但是根号2这个外号还在,那不行,根号2指的是谁啊。
引用理论上是不占内存空间的,但是实际的实现上就是指针的操作。只不过这种指针的操作对编程人员是透明的。
C++引用和函数返回值的更多相关文章
- 【C/C++】引用&的含义/语法/作为函数参数/函数返回值/本质/常量引用
含义 引用不产生副本,只是给原变量起了别名. 对引用变量的操作就是对原变量的操作. 基本语法 数据类型 &别名 = 原名 e.g. int a = 10; int &b = a; // ...
- PHP获取函数返回值的引用
通过在函数前添加&可以获取函数返回值的引用,如:function &test(){return 10;}
- 函数返回值为 const 指针、const 引用
函数返回值为 const 指针,可以使得外部在得到这个指针后,不能修改其指向的内容.返回值为 const 引用同理. class CString { private: char* str; publi ...
- 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数
[源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...
- C++ const修饰函数、函数参数、函数返回值
const修饰函数 在类中将成员函数修饰为const表明在该函数体内,不能修改对象的数据成员而且不能调用非const函数.为什么不能调用非const函数?因为非const函数可能修改数据成员,cons ...
- C++函数返回值(02)
对象作为返回值 编译器会将函数栈中的返回值数据拷贝到返回栈中 指针作为返回值 函数的返回值可以是存储某种类型数据的内存地址,称这种函数为指针函数.它们的一般定义形式如下: 类型标识符 *函数名(参数 ...
- C++函数返回值发生的对象复制
最近用QT做一个监控系统的项目,需要显示目标的运动轨迹,每次目标移动后,就在目标的轨迹中(用vector记录)添加一条新轨迹. 但是在运行中画面里一直不出现轨迹,经过调试发现是记录轨迹的函数出错了. ...
- Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数 目录 Pycharm使用技巧(转载) Python第一天 ...
- 转 Perl函数返回值用法指导
http://developer.51cto.com/art/201007/213003.htm Perl函数返回值用法指导 Perl编程语言中Perl函数返回值用法你是否比较熟悉,这里向大家简单 ...
随机推荐
- Asp.net异步IHttpAsyncHandler示例
/// <summary> /// 异步IHttpHandler,实现了一个简单的统计流量的功能, /// 由于是示例代码,所以没有判断IP或者MAC /// </summary&g ...
- PHP 生成UUID的方法
. . . ...
- memcached 内存管理 分析(转)
Memcached是一个高效的分布式内存cache,了解memcached的内存管理机制,便于我们理解memcached,让我们可以针对我们数据特点进行调优,让其更好的为我所用.这里简单谈一下我对me ...
- Centos升级gcc4.4.7升级gcc4.8手记
本博客来自:http://www.mudbest.com/centos%E5%8D%87%E7%BA%A7gcc4-4-7%E5%8D%87%E7%BA%A7gcc4-8%E6%89%8B%E8%AE ...
- 子级Repeater获取 父级Repeater
第一种方法,子级Repeater中绑定父级的某个字段: <%# DataBinder.Eval((Container.NamingContainer.NamingContainer as Rep ...
- TCP/IP详解之:UDP协议
第11章 UDP协议 UDP首部 UDP的检验和是可选的,而TCP的检验和是必须的: UDP的检验和是端到端的检验和.由发送端计算,由接收端验证: 尽管UDP的检验和是可选的,但总是推荐被使用 IP ...
- struts2源码调试环境的搭建
源码之前,了无秘密. 说一句逼格很高的话来镇镇场子. 这两天在看陆舟的<Struts2技术内幕>,一边看脑子一边冒出四个字:相见恨晚.极力推荐想了解Struts2的人看看这本书,之前一直在 ...
- smarty模版使用php标签,获取模版变量!
<ul>{/foreach from=$A key=k item=val/}{/php/} $val = $this->_tpl_vars[val]; $date = substr( ...
- 【原】YUI Test自动化测试实例详解
测试在软件开发中至关重要,目前针对不同的开发语言,都有比较成熟的测试框架,如jUnit,cUnit,cppUnit,nUnit等,我们统称为xUnit,他们的都遵守统一的规则: 针对代码测试 断言 启 ...
- Django模板-基础知识
上一篇中带参数的URLconf虽然可以做到传参动态显示内容,但是最终现实的内容还是硬编码到Python代码中的 def hours_ahead(request,phours): try: phours ...