这是老师上课讲的内容,现在把它写下来,一方面当做复习,另一方面真的想学点东西。废话不多说,先贴上测试的代码:

 #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++引用和函数返回值的更多相关文章

  1. 【C/C++】引用&的含义/语法/作为函数参数/函数返回值/本质/常量引用

    含义 引用不产生副本,只是给原变量起了别名. 对引用变量的操作就是对原变量的操作. 基本语法 数据类型 &别名 = 原名 e.g. int a = 10; int &b = a; // ...

  2. PHP获取函数返回值的引用

    通过在函数前添加&可以获取函数返回值的引用,如:function &test(){return 10;}

  3. 函数返回值为 const 指针、const 引用

    函数返回值为 const 指针,可以使得外部在得到这个指针后,不能修改其指向的内容.返回值为 const 引用同理. class CString { private: char* str; publi ...

  4. 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数

    [源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...

  5. C++ const修饰函数、函数参数、函数返回值

    const修饰函数 在类中将成员函数修饰为const表明在该函数体内,不能修改对象的数据成员而且不能调用非const函数.为什么不能调用非const函数?因为非const函数可能修改数据成员,cons ...

  6. C++函数返回值(02)

    对象作为返回值 编译器会将函数栈中的返回值数据拷贝到返回栈中 指针作为返回值 函数的返回值可以是存储某种类型数据的内存地址,称这种函数为指针函数.它们的一般定义形式如下:  类型标识符 *函数名(参数 ...

  7. C++函数返回值发生的对象复制

    最近用QT做一个监控系统的项目,需要显示目标的运动轨迹,每次目标移动后,就在目标的轨迹中(用vector记录)添加一条新轨迹. 但是在运行中画面里一直不出现轨迹,经过调试发现是记录轨迹的函数出错了. ...

  8. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数

    Python第七天   函数  函数参数   函数里的变量   函数返回值  多类型传值     函数递归调用   匿名函数   内置函数 目录 Pycharm使用技巧(转载) Python第一天   ...

  9. 转 Perl函数返回值用法指导

    http://developer.51cto.com/art/201007/213003.htm Perl函数返回值用法指导   Perl编程语言中Perl函数返回值用法你是否比较熟悉,这里向大家简单 ...

随机推荐

  1. web api 上传

    using System.Net; using System.Net.Http; using System.Web; using System.Web.Http;   namespace FileUp ...

  2. 再议Swift操作符重载

    今天我们来谈一谈Swift中的操作 符重载,这一功能非常实用,但是也相当有风险.正所谓“能力越大责任越大”,这句话用来形容操作符重载最合适不过了.它可以令你的代码更加简洁,也可以让 一个函数调用变得又 ...

  3. 【C++学习笔记1】

    几个比较容易忘记的东西....... 移动构造函数: Vector(Vector &&copy) //移动构造函数 { if(copy.A!=NULL) { A=copy.A; cop ...

  4. iOS设计模式解析(五)责任链模式

    责任链模式:使多个对象都有机会处理请求,从而避免发送者和接受者之间发生耦合. 应用场景: 有多个对象可以处理请求,而处理程序只有在运行时才能确定 例如: 英雄联盟中伤害计算,伤害类型分为AP.AD.真 ...

  5. mysql中select distinct的用法

    在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但 往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...

  6. java 和 Python 的互调

    http://www.cnblogs.com/lmyhao/p/3363385.html http://blog.csdn.net/wxiaow9000/article/details/5166029 ...

  7. PHP面试题之文件目录操作

    获取文件后缀,遍历目录层次 /** * 5种方式获取文件后缀名 * 这道题其实就是考函数substr() strrchr() array_pop() strrpos() strpos() strrev ...

  8. Cortex-M3和Cortex-M4 Fault异常应用之二 ----- Fault处理函数的实现

    在项目处于调试期间,Fault处理程序可能只是一个断点指令,调试器遇到这个指令后停止程序的运行.默认情况下,由于非硬Fault被禁能,所有发生的非Fault都会上访成硬Fault,因此只要在硬Faul ...

  9. 运用Detours库hook API(原理是改写函数的头5个字节)

    一.Detours库的来历及下载: Detours库类似于WTL的来历,是由Galen Hunt and Doug Brubacher自己开发出来,于99年7月发表在一篇名为<Detours: ...

  10. 利用netstat和tasklist查看PC的端口占用情况

    经常,我们在启动应用的时候发现系统需要的端口被别的程序占用,如何知道谁占有了我们需要的端口? 1.Windows平台在windows命令行窗口下执行: E:\oracle\ora92\bin>n ...