C++学习之路—引用(一)—基础知识
(根据《C++程序设计》(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明)
对一个数据可以建立一个“引用”,它的作用是为一个变量起一个别名。这是C++对C的一个重要扩充。本系列分两篇,本篇为基础篇,主要是介绍基本知识。
1 基本概念及注意事项
1.1 引用概念
假如有一个变量a,想给它起一个别名b,可以这样写:
1: int a ;
2: int &b = a ; //声明b是a的“引用”
以上声明了b是a的引用,即b是a的别名。经过这样的声明后,使用a和b的作用相同,都代表同一个变量。注意:在上述声明中,&是引用声明符,并不代表地址。在数据类型名出现的&是引用声明符,在其他场合出现的都是取地址符。声明变量b为引用,并不需要另外开辟内存单元来存放b的值。b和a占内存中同一内存单元它们具有同一地址。即声明b是a的引用,可以理解为:使变量b具有变量a的地址。
1.2 注意事项
(1)引用不是一种独立的数据类型。对引用只有声明,没有定义。
必须先定义一个变量,然后声明对该对象建立一个引用。关于定义和引用的具体区别,将会在近期的博客中整理。暂时可以简单的这样理解:变量定义,用于为变量分配存储空间,还可为变量指定初始值;变量声明,用于向程序表明变量的类型和名字。
(2)声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。
注意:当引用作为函数形参时不必在声明中初始化,它的初始化是在函数调用时的虚实结合实现的,即作为形参的引用是实参的别名。
(3)声明一个引用后,不能再使之作为另一个变量的引用。
比如声明了b是变量a的引用后,在其有效作用范围内,b始终与其代表的变量a联系,不能在作为其他变量的引用,例如下面的用法就不合法:
1: int a1 ,a2 ;
2: int &b = a1 ; //声明b是a1的引用
3: int &b = a2 ; //试图使b又变成a2的引用,不合法
(4)不能建立引用数组。
下面的用法不合法:
1: int a[5] ;
2: int &b[5] = a ; //错误,不能建立引用数组
3: int &b = a[0] ; //错误,不能建立数组元素的引用
(5)不能建立引用的引用。
下面的用法也不合法:
1: int a = 3 ;
2: int &b = a ; //声明b是a的引用,正确
3: int &c = b ; //错误,试图建立引用的引用
2 引用的应用
唉?好奇怪啊,有了变量名,为什么还需要一个别名呢?C++之所以增加引用机制,主要一个方面就是把它作为函数的参数,以扩充函数传递数据的功能。闲话少说,上例子!
为了说明引用的作用,我们写函数实现两个数据值得交换。有人说这还不简单,信手拈来嘛:
1: void swap (int a ,int b)
2: {
3: int temp = a ;
4: a = b ;
5: b = temp ;
6: }
若在主函数中调用此函数,试图交换变量i和j的值:
1: int i = 3 ;
2: int j = 5 ;
3: swap(i,j) ;
唉,好奇怪,怎么没有得到正确答案呢?这就要说道函数参数传递的机制了,这位同 学想通过改变形参的值,而改变实参的值,但是他用的函数参数传递机制却是:
(1) 将变量名作为实参和形参。
这时传给形参的是变量的值,传递是单向的.如果在执行函数期间形参的值发生变化,并不传回给实参.因为在函数调用时,形参和实参不是同一个存储单元。
那又有同学说了,那可以传递变量的地址啊,说着就写出了下述程序:
1: void swap(int* p1 ,int* p2)
2: {
3: int temp ;
4: temp = *p1 ;
5: *p1 = *p2 ;
6: *p2 = temp ;
7: }
也在主函数中测试了一下:
1: int i = 3 ;
2: int j = 5 ;
3: swap(&i,&j) ;
然后测试i,j的值,得到了正确答案。这位同学是利用了第二种参数传递的机制:
(2)传递变量的地址。
形参是指针变量,实参是一个变量的地址,调用函数时,形参(即指针变量)得到实参变量的地址,从而指向实参变量单元。调用函数时把变量i和j的地址传送给形参p1和p2 。所以p1就指向变量i,p2就指向j。通过交换指针所指的值,当然就交换了i和j 。这种方式通过形参变量指针访问主函数中的变量,并改变它们的值,虽然能得到正确结果,但是在概念上却是兜了一个圈子。下面就介绍第三种写法:
1: void swap(int &a , int &b)
2: {
3: int temp ;
4: temp = a ;
5: a = b ;
6: b = temp ;
7: }
主函数中:
1: int i = 3 ;
2: int j = 5 ;
3: swap(i,j) ;
也得到了正确结果。这里用到了第三种参数传递机制:
(3)以引用作为形参,在虚实结合中建立变量的引用,使形参名作为实参的引用,即形参称为实参的引用。
当main函数调用swap函数时,进行虚实结合,把实参变量i和j的地址传递给形参a和b,使a称为i的别名,b称为j的别名,当然a和b的值交换了,i和j的值也交换了。这就是地址传递方式。
那么这三种传递参数的方式有啥不同呢:
其实上述三种传递方式,可归纳为两种:传值方式和传址方式。
传值方式:(1)和(2)是传值方式,在(1)中,把变量i和j的值传递给形参a和b。在(2)中,把&i和&j的值传递给指针变量p1和p2 。在此方式中实参是地址(&i和&j),传递的是地址,故仍然是传值方式,不是传址方式。传值方式在调用函数时,需要对形参分配存储单元。
传址方式:(3)为此方式,实参不是地址而是变量名,由于形参是引用,系统会自动的将形参的地址传递给形参。注意:此时传送的是地址而不是实参变量的值。
总结一下:用引用形参的方法比使用指针简单、直观、方便,可以部分代替指针的操作。当然这只是引用的用处之一,引用的厉害指出多着呢,待后续娓娓道来。。。
C++学习之路—引用(一)—基础知识的更多相关文章
- IOS学习之路--OC的基础知识
1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch框架 3.Xcode使用 -------------------- CocoaTouc ...
- java学习之路之javaSE基础1
<h2>java学习之路之javaSE基础1</h2> <div> ###01.01_计算机基础知识(计算机概述)(了解)* A:什么是计算机?计算机在生活中的应用 ...
- 学习 shell脚本之前的基础知识
转载自:http://www.92csz.com/study/linux/12.htm 学习 shell脚本之前的基础知识 日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写sh ...
- java学习之路之javaSE基础2
java学习之路之javaSE基础2 所有的代码都是引用他人写的. 1.逻辑运算符 //&,|,^,! //int x = 10; //5 < x < 15 //x > 5 ...
- 【SpringCloud之pigx框架学习之路 】1.基础环境安装
[SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.Cmder.exe安装 (1) windows常用命令行工具 下 ...
- 【转载】salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句
salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句 salesforce如果简单的说可以大概分成两个部分:Apex,VisualForce Page. 其中Apex ...
- JVM菜鸟进阶高手之路十(基础知识开场白)
转载请注明原创出处,谢谢! 最近没有什么实战,准备把JVM知识梳理一遍,先以开发人员的交流来谈谈jvm这块的知识以及重要性,依稀记得2.3年前用solr的时候老是经常oom,提到oom大家应该都不陌生 ...
- 学习shell脚本之前的基础知识
日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写shell脚本,那么你就不算一个合格的管理员.目前很多单位在招聘linux系统管理员时,shell脚本的编写是必考的项目.有的单位 ...
- Python学习系列(二)(基础知识)
Python基础语法 Python学习系列(一)(基础入门) 对于任何一门语言的学习,学语法是最枯燥无味的,但又不得不学,基础概念较繁琐,本文将不多涉及概念解释,用例子进行相关解析,适当与C语言对比, ...
- VBS学习日记(二) 基础知识
VBScript 基础知识 一.变量 1.全部单引號后面的内容都被解释为凝视.(在vbsedit中ctrl+m凝视,反凝视ctrl+shift+m) 2.在 VBScript 中,变量的命名规则遵循标 ...
随机推荐
- poemel 端口作用
clientPort 用于connetor组件启动时候,监听的调用,用于客户端连接 port用于服务器间通信,即rpc调用时候使用,在remote组件启动时候,生成remote,即gateway实例, ...
- 再见了acm
2013年11月17日长沙区域赛我的最后一场区域赛. 忙碌了三年的acm要停下脚步,一时还无法接受. 这样一个结果有点无奈. 感谢队友,三年三支队伍五个队友,感谢你们.(每当写到这里时就总有点小忍不住 ...
- hdu 4784 Dinner Coming Soon
spfa+优先队列.刚开始只用的spfa,结果tle到死.然后听队友说要用到优先队列,想了想,对时间分层的话的确每一个结点都只进队列一次即可,因为只有大时间才能更新出小时间,然后就wa成shi了.按队 ...
- Android 中 ListView 常用属性合集
class ListView.FixedViewInfo//用来在列表内展现一个固定位置视图,如在列表顶端的header和在列表底端的footer 一.XML属性 1.ListView的XML属性 a ...
- Python 模块续和面向对象的介绍(六)
一.基本模块 shutil 文件.目录.压缩包的处理模块 shutil.copyfile(src, dst) 拷贝文件 >>> shutil.copyfile('a.log','b. ...
- UASCO Zero Sum DFS + Stack
给一个N 表示1 2 3 ...N 求出所有 zero sum的情况 [简单Dfs 即可] 运算结果的时候我使用了一个stack... 比如N = 7 那么要求输出 1+2-3+4-5-6+7 1+2 ...
- host字段变复杂了
声明: 本博客欢迎转载,但请保留原作者信息! 作者:李人可 团队:华为杭州OpenStack团队 讨论的是openstack中卷的host属性. 印象中.社区H版本号对于volume的host值表示的 ...
- 找唯一不出现三次而出现1次的数子O(n)位运算算法
之前两次那个是异或运算处理.这次以为也是类似.可是没想出来. 高富帅想出来了算法,转为bitset,然后加起来 同样的话 要么0+0+0 要么1+1+1,最后剩下的 能够通过%3 算出0 或1.思想是 ...
- 两个activity之间的数据传递
1.清单文件第二个activity<activity android:name="com.example.twodatapass.ResultActivity" androi ...
- IOS引导页的编写
我们在第一次打开App的时候,通常不是直接进入App主界面,而是会有一个能左右滑动.介绍App功能的界面.我是用NSUserDefaults + UIScrollview实现. 新建一个类,继承UIV ...