C++的引用的使用
1引用的定义
引用时C++对C的一个重要的扩充,引用的作用是给变量起一个别名。
例如:
int a;
int &b=a;//声明b是a的引用
经过以上的声明,b就成为了a的别名,a和b的地位以及作用都是一样的。
将b声明为a的引用,不需要再为b开辟新的单元,b和a在内存中占同一存储单元,它们具有相同的地址。
#include<iostream>
using namespace std;
int main(){
int a=10;
int &b=a;//声明b是a的引用
cout<<"b="<<b<<endl;
a=a-5;
cout<<"b="<<b<<endl;
b=b-1;
cout<<"a="<<a<<endl;
return 0;
}
在程序中,
声明了b是a的引用,然后输出b=10;
然后使a的值减小5,再输出b=5,说明b会随着a的变化做出变化;
然后使b的值减小1,再输出a=4,说明a会随着b的变化做出变化。
在声明一个引用的同时,必须同时对它进行初始化,即声明它代表哪一个变量。在声明变量b是变量a的引用后,就可以将b作为a的别名来进行操作,并且b不能再作为其他变量的引用(别名)。
声明引用,而不进行初始化操作:
#include<iostream>
using namespace std;
int main(){
int a=10;
int &b;
return 0;
}
编辑器报错
========================================
已经申明p为a的引用之后,在声明p为b的引用
#include<iostream>
using namespace std;
int main(){
int a=10;
int &p=a;
int b=5;
int &p=b;
return 0;
}
编辑器报错:
注意区分:
int &b=a;表示b是a的引用
int *b=&a;表示b是指针变量,并且b的值是a的地址
引用不是一种独立的数据类型,必须指定其代表的某一类实体(如变量,类对象),不能定义引用数组,不能定义指向引用的指针,也不能定义指针的引用。
2 引用作为函数的参数
C++增加引用机制,主要是把它作为函数参数,以扩充函数传递数据的功能。
函数的参数传递有三种情况
将变量名作为形参和实参
这是传给形参的是变量的值,传递是单向的。如果在执行被调用函数期间,形参的值发生变化,是不能反映到实参的。因为形参只是复制了实参的数值,两变量并不是占用同一存储单元。
#include<iostream>
using namespace std;
int main(){
void change(int x,int y);
int i=3,j=2;
change(i,j);
cout<<i<<endl;
cout<<j<<endl;
return 0;
}
void change(int x,int y){
int z;
z=x;
x=y;
y=z;
}
x复制了i的值,y复制了j的值。但i和j与x和y占不同的存储单元,因此只改变x和y的值,并不能改变i和j的值。
将变量地址作为实参,指针作为形参
这种方式仍然是值传递的方式,不过他传递的不是变量的数值,而是变量的地址。因此可以在被调用函数中,通过调用指针指向的变量来改变相应变量的值。
#include<iostream>
using namespace std;
int main(){
void change(int * x,int * y);
int i=3,j=2;
change(&i,&j);
cout<<i<<endl;
cout<<j<<endl;
return 0;
}
void change(int * x,int * y){
int *z;
z=x;
x=y;
y=z;
}
因为是值传递,所以只改变指针的值,而不去改变指向的变量的值,还是不能改变相应的变量的值。
#include<iostream>
using namespace std;
int main(){
void change(int * x,int * y);
int i=3,j=2;
change(&i,&j);
cout<<i<<endl;
cout<<j<<endl;
return 0;
}
void change(int * x,int * y){
int *z;
*z=*x;
*x=*y;
*y=*z;
}
当改变指针指向的变量的值的时候,相应的变量的数值也会发生变化。
将变量名作为实参,引用作为形参
将变量名作为形参和实参和将变量地址作为实参,指针作为形参都是采用的值传递的方式。而引用作为形参的时候,采用的是地址传递的方式。
#include<iostream>
using namespace std;
int main(){
void change(int & x,int & y);
int i=3,j=2;
change(i,j);
cout<<i<<endl;
cout<<j<<endl;
return 0;
}
void change(int & x,int & y){
int z;
z=x;
x=y;
y=z;
}
在函数change的形参中声明了a,b是整形变量的引用。当main函数调用change函数时,把实参i的地址传递给形参x,把实参j的地址传递给形参y,从而使i和x共享同一个单元,使j和y共享同一个单元。也可以理解成,把i的变量名传递给了x,把j的变量名传递给了y。
引用作为形参与指针变量作为形参的区别
1使用引用类型,就不必在swap函数中声明形参是指针变量。指针变量要另外开辟内存单元,其内容是地址。而引用不是一个独立的变量,不单独占内存单元,引用的数据类型应该应该与实参相同。
2 在main函数中,实参不必用变量的地址,而是直接用变量名。系统向形参传递的是实参的地址而不是实参的值。
3 由于不能声明指针的引用,那我们如何像指针那样传递可以通过传递数组的首元素来实现传递整个数组的数据呢?
使用指针作为形参:
#include<iostream>
using namespace std;
int main(){
void Print(int *p,int n);
int a[5]={1,2,3,4,5};
Print(a,5);
return 0;
}
void Print(int *p,int n){
int i;
for(i=0;i<n;i++){
cout<<p[i]<<endl;
}
}
=============================================================================
使用引用作为形参
#include<iostream>
using namespace std;
int main(){
void Print(int &p,int n);
int a[5]={1,2,3,4,5};
Print(a[0],5);
return 0;
}
void Print(int &p,int n){
int i;
int *a=&p;
for(i=0;i<n;i++){
cout<<a[i]<<endl;
}
}
因为引用就是给原来的变量起了别名,并且不能声明指针的引用,所以我们就声明指针指向的变量的引用,然后再对引用取地址,就达到了这个目的。
为了更清楚的说明,下面再举一个例子:
#include<iostream>
using namespace std;
int main(){
int i=10;
int *p;
p=&i;//将i的地址赋给指针p
int &y=*p;//将y作为指针p指向的变量的引用
cout<<y<<endl;
if(&y==p)cout<<"succeed"<<endl;//检查y的地址和指针p的值是否相等
return 0;
}
#include<iostream>
using namespace std;
int main(){
int a[5]={1,2,3,4,5};
int &y=a[0];//声明y作为数组的首元素的引用
int *p=&y;//将y的地址赋给指针p
int i=0;
for(;i<5;i++){
cout<<p[i]<<endl;
}
return 0;
}
C++的引用的使用的更多相关文章
- 【.net 深呼吸】序列化中的“引用保留”
假设 K 类中有两个属性/字段的类型相同,并且它们引用的是同一个对象实例,在序列化的默认处理中,会为每个引用单独生成数据. 看看下面两个类. [DataContract] public class 帅 ...
- CSS 选择器及各样式引用方式
Css :层叠样式表 (Cascading Style Sheets),定义了如何显示HTML元素. 目录 1. 选择器的分类:介绍ID.class.元素名称.符合.层次.伪类.属性选择器. 2. 样 ...
- Android性能优化之巧用软引用与弱引用优化内存使用
前言: 从事Android开发的同学都知道移动设备的内存使用是非常敏感的话题,今天我们来看下如何使用软引用与弱引用来优化内存使用.下面来理解几个概念. 1.StrongReference(强引用) 强 ...
- C++中的引用
一,C++中引用的基础知识 1.引用的基本概念 1.所谓的引用其实就是对变量起“别名”.引用和变量对应得是相同的内存,修改引用的值,变量的值也会改变,和指针类似. 2.引用在定义的时候必须要初始化,初 ...
- Java 为值传递而不是引用传递
——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...
- EC笔记:第4部分:21、必须返回对象时,别返回引用
使用应用可以大幅减少构造函数与析构函数的调用次数,但是引用不可以滥用. 如下: struct St { int a; }; St &func(){ St t; return t; } 在返回t ...
- EC笔记:第4部分:20、传递引用代替传值
考虑以下场景: #include <iostream> #include <string> using namespace std; struct Person { strin ...
- 编译器开发系列--Ocelot语言2.变量引用的消解
"变量引用的消解"是指确定具体指向哪个变量.例如变量"i"可能是全局变量i,也可能是静态变量i,还可能是局部变量i.通过这个过程来消除这样的不确定性,确定所引用 ...
- C++右值引用浅析
一直想试着把自己理解和学习到的右值引用相关的技术细节整理并分享出来,希望能够对感兴趣的朋友提供帮助. 右值引用是C++11标准中新增的一个特性.右值引用允许程序员可以忽略逻辑上不需要的拷贝:而且还可以 ...
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
随机推荐
- 在struts2.5版本中使用DMI遇到问题
struts2.5 为了提升安全性,添加了 allomethod 这么个玩意. 解决方法是在配置文件中添加: <package name="exam" extends=&qu ...
- 09-THREE.JS 物体缩放,坐标,旋转,位移,是否可见
<!DOCTYPE html> <html> <head> <title></title> <script src="htt ...
- 20180907_网络差_天安微信token请求超时
一.异常现象 token请求时,显示请求超时. 二.原因分析 这个异常有如下几个原因: (1)服务器没有开通 qyapi.weixin.qq.com 的外网权限 (2)服务器网络太慢 三.异常解决 ...
- SQLAlchemyの增删改查
用a*my写原味sql from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, I ...
- 安装Aptana时检测不到已经安装的Nodejs
1.环境前提 已经安装了Git和Nodejs,在安装Aptana时任然提示如下错误: Failed to correctly acquire installer_nodejs_windows.msi ...
- SVN客户端与服务器端搭建
一.客户端安装 1.点击安装程序 2.修改svn安装位置 3.开始安装 4.安装完成 5.回到左面 右键出现svn检出 tortoiSVN 表示安装成功 二.SVN服务端安装 1.点击服务端安装 ...
- 20179203 《Linux内核原理与分析》第十一周作业
一.环境的使用和搭建 首先我的攻击机和靶机都搭建在虚拟机上,选用的是VMware Workstation Pro虚拟机. 攻击机选用的是Linux kali 2017.2版本,而靶机安装的是XP sp ...
- QQ帐户的申请与登陆(25 分)
实现QQ新帐户申请和老帐户登陆的简化版功能.最大挑战是:据说现在的QQ号码已经有10位数了. 输入格式: 输入首先给出一个正整数N(≤),随后给出N行指令.每行指令的格式为:“命令符(空格)QQ号码( ...
- [SPOJ10707]Count on a tree II
luogu 题意 给定一个n个节点的树,每个节点表示一个整数,问u到v的路径上有多少个不同的整数. sol 也就是路径数颜色.树上莫队板子题. 我这种分块的姿势貌似是假的. 所以跑的是最慢的QAQ. ...
- Unity 5 官方打包管理工具 Asset Bundle Manager
http://blog.csdn.net/suifcd/article/details/51570003 Unity5在Asset bundle 打包管理上采用了全新的方式,不需要再对每个文件进行MD ...