(根据《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++学习之路—引用(一)—基础知识的更多相关文章

  1. IOS学习之路--OC的基础知识

    1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch框架 3.Xcode使用 -------------------- CocoaTouc ...

  2. java学习之路之javaSE基础1

    <h2>java学习之路之javaSE基础1</h2> <div> ###01.01_计算机基础知识(计算机概述)(了解)* A:什么是计算机?计算机在生活中的应用 ...

  3. 学习 shell脚本之前的基础知识

    转载自:http://www.92csz.com/study/linux/12.htm  学习 shell脚本之前的基础知识 日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写sh ...

  4. java学习之路之javaSE基础2

    java学习之路之javaSE基础2 所有的代码都是引用他人写的. 1.逻辑运算符 //&,|,^,! //int x = 10; //5 < x < 15 //x > 5 ...

  5. 【SpringCloud之pigx框架学习之路 】1.基础环境安装

    [SpringCloud之pigx框架学习之路 ]1.基础环境安装 [SpringCloud之pigx框架学习之路 ]2.部署环境 1.Cmder.exe安装 (1) windows常用命令行工具 下 ...

  6. 【转载】salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句

    salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句 salesforce如果简单的说可以大概分成两个部分:Apex,VisualForce Page. 其中Apex ...

  7. JVM菜鸟进阶高手之路十(基础知识开场白)

    转载请注明原创出处,谢谢! 最近没有什么实战,准备把JVM知识梳理一遍,先以开发人员的交流来谈谈jvm这块的知识以及重要性,依稀记得2.3年前用solr的时候老是经常oom,提到oom大家应该都不陌生 ...

  8. 学习shell脚本之前的基础知识

    日常的linux系统管理工作中必不可少的就是shell脚本,如果不会写shell脚本,那么你就不算一个合格的管理员.目前很多单位在招聘linux系统管理员时,shell脚本的编写是必考的项目.有的单位 ...

  9. Python学习系列(二)(基础知识)

    Python基础语法 Python学习系列(一)(基础入门) 对于任何一门语言的学习,学语法是最枯燥无味的,但又不得不学,基础概念较繁琐,本文将不多涉及概念解释,用例子进行相关解析,适当与C语言对比, ...

  10. VBS学习日记(二) 基础知识

    VBScript 基础知识 一.变量 1.全部单引號后面的内容都被解释为凝视.(在vbsedit中ctrl+m凝视,反凝视ctrl+shift+m) 2.在 VBScript 中,变量的命名规则遵循标 ...

随机推荐

  1. 小猪猪逆袭成博士之C++基础篇(三)字符串

    小猪猪逆袭成博士之C++基础篇(三)字符串 String 写在题外的话: 非常感谢在我发了第一篇随笔以后有很多人看还评论了,这大概就是一种笔记性质的,也不一定全对,如果不对的地方请指出来让我加以改正. ...

  2. HDU 3932 Groundhog Build Home 【基础模拟退火】

    和刚才那道是一模一样 不过求的是最小的,只要稍微修改一下就可以了~ //#pragma comment(linker, "/STACK:16777216") //for c++ C ...

  3. Tcl语言笔记之一

    1,一个TCL脚本可以包含一个或多个命令.命令之间必须用换行符或分号隔开 2,置换 substitution %set y x+100                               // ...

  4. 分析一个socket通信: server/client

    分析一个socket通信: server/client1 server 1. 创建一个server_socket文件,并绑定端口,然后监听端口 (socket, bind, listen) 2. 查询 ...

  5. Qt 内存管理机制

    这篇文章首先发布于我的主页 http://www.devbean.info,以后也会直接发布在那里.现在有 Flex 4 的一篇和 <从 C++ 到 Objective-C>系列,感谢大家 ...

  6. listview滑动

    单击其中的一个item时,让这个item能滚动的listview的顶部.现在用 list.scrollTo(0, item.getTop()); 实现啦 android listview滚动到顶部 转 ...

  7. Jquery学习笔记:通过层次关系获取jquery对象

    前面一篇文章,我们介绍了如何通过web标签的id , css样式值来获取jquery对象. 但这只是基本方法,不能满足所有场景的需求. 本文介绍通过dom元素之间的层次关系获取元素.具体是将各种标识符 ...

  8. haroxy hdr

    ACL derivatives :ACL的衍生物 hdr([<name>[,<occ>]]) : exact string match 字符串精确匹配 hdr_beg([< ...

  9. Swift - 禁用UIWebView和WKWebView的下拉拖动效果

    使用UIWebView或WKWebView加载网页时,如果页面处于最顶端时,用户用手指往下拖动,会露出灰色空背景.同样页面在最底部的时候,继续向上拖动,下方也会露出空背景. 要禁止这个拖动效果,可进行 ...

  10. linux登录windows服务器

    在公司同时也兼顾了王老师会议网站的任务,我喜欢用linux,而会议网站托管在windows系统上,虽然装了双系统,但我还是比较懒,不喜欢经常切换系统.还好,linux可以实现登录windows服务器. ...