1引用的定义

引用时C++对C的一个重要的扩充,引用的作用是给变量起一个别名。

例如:

int a;

int &b=a;//声明b是a的引用

经过以上的声明,b就成为了a的别名,a和b的地位以及作用都是一样的。

将b声明为a的引用,不需要再为b开辟新的单元,b和a在内存中占同一存储单元,它们具有相同的地址。

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4.          int a=10;
  5.          int &b=a;//声明b是a的引用
  6.          cout<<"b="<<b<<endl;
  7.          a=a-5;
  8.          cout<<"b="<<b<<endl;
  9.          b=b-1;
  10.          cout<<"a="<<a<<endl;            
  11.          return 0;
  12. }

在程序中,

声明了b是a的引用,然后输出b=10;

然后使a的值减小5,再输出b=5,说明b会随着a的变化做出变化;

然后使b的值减小1,再输出a=4,说明a会随着b的变化做出变化。

在声明一个引用的同时,必须同时对它进行初始化,即声明它代表哪一个变量。在声明变量b是变量a的引用后,就可以将b作为a的别名来进行操作,并且b不能再作为其他变量的引用(别名)。

声明引用,而不进行初始化操作:

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int a=10;
  5. int &b;
  6. return 0;
  7. }

编辑器报错

========================================

已经申明p为a的引用之后,在声明p为b的引用

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int a=10;
  5. int &p=a;
  6. int b=5;
  7. int &p=b;
  8. return 0;
  9. }

编辑器报错:

注意区分:

int &b=a;表示b是a的引用

int *b=&a;表示b是指针变量,并且b的值是a的地址

引用不是一种独立的数据类型,必须指定其代表的某一类实体(如变量,类对象),不能定义引用数组,不能定义指向引用的指针,也不能定义指针的引用。

2 引用作为函数的参数

C++增加引用机制,主要是把它作为函数参数,以扩充函数传递数据的功能。

函数的参数传递有三种情况

将变量名作为形参和实参

这是传给形参的是变量的值,传递是单向的。如果在执行被调用函数期间,形参的值发生变化,是不能反映到实参的。因为形参只是复制了实参的数值,两变量并不是占用同一存储单元。

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. void change(int x,int y);
  5. int i=3,j=2;
  6. change(i,j);
  7. cout<<i<<endl;
  8. cout<<j<<endl;
  9. return 0;
  10. }
  11. void change(int x,int y){
  12. int z;
  13. z=x;
  14. x=y;
  15. y=z;
  16. }

x复制了i的值,y复制了j的值。但i和j与x和y占不同的存储单元,因此只改变x和y的值,并不能改变i和j的值。

将变量地址作为实参,指针作为形参

这种方式仍然是值传递的方式,不过他传递的不是变量的数值,而是变量的地址。因此可以在被调用函数中,通过调用指针指向的变量来改变相应变量的值。

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. void change(int * x,int * y);
  5. int i=3,j=2;
  6. change(&i,&j);
  7. cout<<i<<endl;
  8. cout<<j<<endl;
  9. return 0;
  10. }
  11. void change(int * x,int * y){
  12. int *z;
  13. z=x;
  14. x=y;
  15. y=z;
  16. }

因为是值传递,所以只改变指针的值,而不去改变指向的变量的值,还是不能改变相应的变量的值。

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. void change(int * x,int * y);
  5. int i=3,j=2;
  6. change(&i,&j);
  7. cout<<i<<endl;
  8. cout<<j<<endl;
  9. return 0;
  10. }
  11. void change(int * x,int * y){
  12. int *z;
  13. *z=*x;
  14. *x=*y;
  15. *y=*z;
  16. }

当改变指针指向的变量的值的时候,相应的变量的数值也会发生变化。

将变量名作为实参,引用作为形参

将变量名作为形参和实参和将变量地址作为实参,指针作为形参都是采用的值传递的方式。而引用作为形参的时候,采用的是地址传递的方式。

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. void change(int & x,int & y);
  5. int i=3,j=2;
  6. change(i,j);
  7. cout<<i<<endl;
  8. cout<<j<<endl;
  9. return 0;
  10. }
  11. void change(int & x,int & y){
  12. int z;
  13. z=x;
  14. x=y;
  15. y=z;
  16. }

在函数change的形参中声明了a,b是整形变量的引用。当main函数调用change函数时,把实参i的地址传递给形参x,把实参j的地址传递给形参y,从而使i和x共享同一个单元,使j和y共享同一个单元。也可以理解成,把i的变量名传递给了x,把j的变量名传递给了y。

引用作为形参与指针变量作为形参的区别

1使用引用类型,就不必在swap函数中声明形参是指针变量。指针变量要另外开辟内存单元,其内容是地址。而引用不是一个独立的变量,不单独占内存单元,引用的数据类型应该应该与实参相同。

2 在main函数中,实参不必用变量的地址,而是直接用变量名。系统向形参传递的是实参的地址而不是实参的值。

3 由于不能声明指针的引用,那我们如何像指针那样传递可以通过传递数组的首元素来实现传递整个数组的数据呢?

使用指针作为形参:

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. void Print(int *p,int n);
  5. int a[5]={1,2,3,4,5};
  6. Print(a,5);
  7. return 0;
  8. }
  9. void Print(int *p,int n){
  10. int i;
  11. for(i=0;i<n;i++){
  12. cout<<p[i]<<endl;
  13. }
  14. }

=============================================================================

使用引用作为形参

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. void Print(int &p,int n);
  5. int a[5]={1,2,3,4,5};
  6. Print(a[0],5);
  7. return 0;
  8. }
  9. void Print(int &p,int n){
  10. int i;
  11. int *a=&p;
  12. for(i=0;i<n;i++){
  13. cout<<a[i]<<endl;
  14. }
  15. }

因为引用就是给原来的变量起了别名,并且不能声明指针的引用,所以我们就声明指针指向的变量的引用,然后再对引用取地址,就达到了这个目的。

为了更清楚的说明,下面再举一个例子:

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int i=10;
  5. int *p;
  6. p=&i;//将i的地址赋给指针p
  7. int &y=*p;//将y作为指针p指向的变量的引用
  8. cout<<y<<endl;
  9. if(&y==p)cout<<"succeed"<<endl;//检查y的地址和指针p的值是否相等
  10. return 0;
  11. }

  1. #include<iostream>
  2. using namespace std;
  3. int main(){
  4. int a[5]={1,2,3,4,5};
  5. int &y=a[0];//声明y作为数组的首元素的引用
  6. int *p=&y;//将y的地址赋给指针p
  7. int i=0;
  8. for(;i<5;i++){
  9. cout<<p[i]<<endl;
  10. }
  11. return 0;
  12. }

C++的引用的使用的更多相关文章

  1. 【.net 深呼吸】序列化中的“引用保留”

    假设 K 类中有两个属性/字段的类型相同,并且它们引用的是同一个对象实例,在序列化的默认处理中,会为每个引用单独生成数据. 看看下面两个类. [DataContract] public class 帅 ...

  2. CSS 选择器及各样式引用方式

    Css :层叠样式表 (Cascading Style Sheets),定义了如何显示HTML元素. 目录 1. 选择器的分类:介绍ID.class.元素名称.符合.层次.伪类.属性选择器. 2. 样 ...

  3. Android性能优化之巧用软引用与弱引用优化内存使用

    前言: 从事Android开发的同学都知道移动设备的内存使用是非常敏感的话题,今天我们来看下如何使用软引用与弱引用来优化内存使用.下面来理解几个概念. 1.StrongReference(强引用) 强 ...

  4. C++中的引用

    一,C++中引用的基础知识 1.引用的基本概念 1.所谓的引用其实就是对变量起“别名”.引用和变量对应得是相同的内存,修改引用的值,变量的值也会改变,和指针类似. 2.引用在定义的时候必须要初始化,初 ...

  5. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  6. EC笔记:第4部分:21、必须返回对象时,别返回引用

    使用应用可以大幅减少构造函数与析构函数的调用次数,但是引用不可以滥用. 如下: struct St { int a; }; St &func(){ St t; return t; } 在返回t ...

  7. EC笔记:第4部分:20、传递引用代替传值

    考虑以下场景: #include <iostream> #include <string> using namespace std; struct Person { strin ...

  8. 编译器开发系列--Ocelot语言2.变量引用的消解

    "变量引用的消解"是指确定具体指向哪个变量.例如变量"i"可能是全局变量i,也可能是静态变量i,还可能是局部变量i.通过这个过程来消除这样的不确定性,确定所引用 ...

  9. C++右值引用浅析

    一直想试着把自己理解和学习到的右值引用相关的技术细节整理并分享出来,希望能够对感兴趣的朋友提供帮助. 右值引用是C++11标准中新增的一个特性.右值引用允许程序员可以忽略逻辑上不需要的拷贝:而且还可以 ...

  10. 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

    作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...

随机推荐

  1. ionic2——环境配置篇

    环境配置 安装nodeJS 配置cnpm 安装ionic2 安装cordova 安装java sdk 安装android sdk(在项目最后打包时app的时候会用到,前期是在浏览器环境测试开发暂时不需 ...

  2. selenium-webdirver api-定位方式

    1,8种单数定位方式 # 通过ID定位目标元素 driver.find_element_by_id('i1') # 通过className定位目标元素 driver.find_element_by_c ...

  3. kylin_异常_02_java.lang.NoClassDefFoundError: org/apache/hadoop/hive/conf/HiveConf 解决办法

    一.异常现象 在kylin的web管理界面,设置hive数据源时,报错: 查找kylin的日志时发现,弹出提示框的原因是因为出现错误: ERROR [http-bio-7070-exec-10] co ...

  4. Python网络编程2018-01-26更新

    前言:使用python3.x写的socket编程,本人wechat:YWNlODAyMzU5MTEzMTQ=. 如果内容有错,请指出来. ssh服务端 # 1.接收一个连接实例 # 2.接收数据 # ...

  5. L119

    A big collaboration is trying to understand diseases of the psycheDiseases of the psyche have always ...

  6. 15_游戏编程模式EventQueue

    #### 两个例子 .GUI event loop ``` while (running) { // 从事件队列里获取一个事件 Event event = getNextEvent(); // Han ...

  7. OSI七层与TCP/IP五层网络架构

    OSI七层模型   OSI中的层 功能 TCP/IP协议族 应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层 数据格式化,代 ...

  8. 图片上传-本地图片转base64+ie8支持+本地预览支持

    最近项目由于flash同学没在了,图片上传只能前端重新做,后台希望用base64数据上传,复用之前接口 问题来了, 1.ie8 不支持canvas转base64 2.本地预览 base64数据,ie8 ...

  9. [独孤九剑]Oracle知识点梳理(七)数据库常用对象之Cursor

    本系列链接导航: [独孤九剑]Oracle知识点梳理(一)表空间.用户 [独孤九剑]Oracle知识点梳理(二)数据库的连接 [独孤九剑]Oracle知识点梳理(三)导入.导出 [独孤九剑]Oracl ...

  10. 1、在Eclipse中安装TestNG(离线方式)

    1.TestNG安装包:链接: https://pan.baidu.com/s/1UXZlJfrp8LM-6XmDLzVXKg 密码: 46y2 2.安装教程: (1).下载testNG 离线安装包[ ...