C++—引用的作用
引入
C语言中函数有两种传参的方式: 传值和传址。以传值方式, 在函数调用过程中会生成一份临时变量用形参代替, 最终把实参的值传递给新分配的临时变量即形参。 它的优点是避免了函数调用的一些副作用, 但是它无法改变实参的值。函数调用完成之后实参的值不会发生改变, 如果要改变实参的值, 只能通过指针传地址过去。
void swap (int left, int right)
{
int temp = left;
left = right;
right = temp;
}
void swap (int *_pleft , int * _pRight)
{
assert (NULL ! = _pleft && NULL ! = _pRight) ;
int iTemp = * _pleft;
*_pleft = * _pRight;
*_pRight = iTemp;
13 }
通过传地址的方式是可以解决问题, 但是传指针也有诸多隐患,很容易出现各种“安全事故”。就如同你想剪指甲,别人却给了你一把杀猪刀,这不是大材小用么。因此C++中 引 入了一种新的类型--引用 。引用只是一个别名,它既解决了传值的缺陷,又不具有传地址的隐患,所以应用广泛
void swap (int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
引用概念
引用(reference)不是新定义一个变量, 而是给已存在的对象取了 一个别名 ,引用类型,引用另外一种类型。 编译器不会为引用对象新开辟内存空间, 它和它引用的对象共用同一块内存空间 。
int num = ;
int &number = num; //number指向num(是num的另外一个名字)
一般在初始化变量时,初始值会被拷贝到新建的对象中。在定义引用时程序把引用和他的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成引用就将和他的初始对象一直绑定在一块(同生共死)。你无法将引用重新绑定到另外一个对象上。
引用即别名
引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。就好像一个人的名字本来叫张三,然后大家又给他取了一个名字叫阿三,其实张三和阿三是同一个人。定义一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的:
number = ; //把120赋给number指向的对象,此处即是赋给了num
int tmp = number; //与tmp = num执行结果一样
为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以引用绑定的对象作为初始值。
引用的定义
(1)允许在一条语句中定义多个引用,其中每个引用标识符都必须以&开头;
(2)因为无法将引用重新绑定到另外一个对象上,因此引用必须初始化。
(3)因为引用本身不是一一个对象,所以不能定义引用的引用。
(4)一个变量可以有多个引用,而一个引用只能给一个变量对象 。
(5)引用的类型要和与之绑定的对象严格匹配(不严谨)。
(6)引用只能绑定在对象上而不能和字面值或某个表达式计算的过程绑定在一起。
int i1 = , i2 = ; //i1和i2都是int型
int &r1 = i1, &r2 = i2; //r1和r2都是引用
int &r3 ; //报错:引用必须初始化
int &r4 = i1, &r5 = i2; //r1, r4同为i1的引用,r2, r5同为i2的引用
int &r4 = i2, &r5 = i1; //报错:r4不能同时分别为i1和i2的引用
int &r6 = ; //报错:引用类型的初始值必须是一个对象
double i3 = 3.14;
int &r7 = i3; //报错:此处引用类型的初始值必须是int型对象
引用与指针
相同点:
底层的实现方式相同, 都是按照指针的方式来实现的:
不同点:
(1)定义上的区别:可以说指针即地址,因为指针是一个存储地址的变量,它指向内存的一个存储单元;引用即别名,引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。
1 int a=1;int *p=&a;
2 //定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。
3 int a=1;int &b=a;
4 //定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单元。
(2)指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;
(3)引用定义时必须初始化,且在进行初始化后就不会再改变了。 指针可以不用, 正常情况下需初始化为NULL,且指针的值在初始化后可以改变,即指向其它的存储单元;
(4)sizeof求取的值不一样,"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小;
(5)指针和引用的自增(++)与自减(--)运算意义不一样, 引 用自 加改变变量的内 容, 指针自 加改变了 指针指向;
(6)可以有多级指针, 但是没有多级引 用,(int **p;合法 而 int &&a是不合法的);
(7)指针和引用的地址不同,引用的地址即所引用对象的地址。指针的地址就是它自己的地址,是内存中的一块实实在在的另一块内存;
(8)引用比指针更安全。不会出现像野指针这样的现象。
指针和引用作为函数参数进行传递时的区别
#include<iostream>
using namespace std; void swap(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
}
int main(void)
{
int a=,b=;
swap(&a,&b);
cout<<a<<" "<<b<<endl;
system("pause");
return ;
}
输出结果为:20 10
用指针传递参数,可以实现对实参进行改变的目的,是因为传递过来的是实参的地址,因此使用*a实际上是取存储实参的内存单元里的数据,即是对实参进行改变,因此可以达到目的。
但是请看下面这个程序:
void test(int *p)
{
int a=;
p=&a;
cout<<p<<" "<<*p<<endl;
}
int main(void)
{
int *p=NULL;
test(p);
if(p==NULL)
cout<<"指针p为NULL"<<endl;
system("pause");
return ;
}
运行结果为:
0x22ff44 1
指针p为NULL
为什么会这样呐?不是传递的地址么,怎么 p 会是NULL?事实上,在 main 函数中声明了一个指针p,并赋值为NULL,当调用 test 函数时,事实上传递的也是地址,只不过传递的是值地址。什么意思呢?也就是说将指针作为参数进行传递时,实际上和传值形式的传参是相同的,只不过拷贝的的是地址。当把指针作为参数进行传递时,也是将实参的一个拷贝传递给形参,即上面程序 main 函数中的 p 和 test 函数中使用的 p 不是同一个变量,存储2个变量 p 的单元也不相同,即两个指针它们自己的地址不同(只是2个 p 指向同一个存储单元,里面保存的是同样的值),那么在 test 函数中对 p 进行修改,并不会影响到 main 函数中的 p 的值。
如果要想达到同时修改 main 函数中 p 的目的,就得使用二级指针或者引用了。
void test(int *&p)
{
int a=;
p=&a;
cout<<p<<" "<<*p<<endl;
}
int main(void)
{
int *p=NULL;
test(p);
if(p!=NULL)
cout<<"指针p不为NULL"<<endl;
system("pause");
return ;
}
输出结果为:0x22ff44 1
指针p不为NULL
引用作为函数参数进行传递时,实质上传递的是实参本身,即传递进来的不是实参的一个拷贝,因此对形参的修改其实是对实参的修改,所以在用引用进行参数传递时,不仅节约时间,而且可以节约空间。
参考:http://www.cnblogs.com/dolphin0520/
C++—引用的作用的更多相关文章
- C++引用的作用和用法
引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样. 引用的声明方法:类型标识符&引用名=目标变量名: 例如: int q; int &ra=a; 说明: &am ...
- C++引用的作用
引入 C语言中函数有两种传参的方式: 传值和传址.以传值方式, 在函数调用过程中会生成一份临时变量用形参代替, 最终把实参的值传递给新分配的临时变量即形参. 它的优点是避免了函数调用的副作用, 确无法 ...
- 引用的作用&引用与指针的区别
引入 C语言中函数有两种传参的方式: 传值和传址.以传值方式, 在函数调用过程中会生成一份临时变量用形参代替, 最终把实参的值传递给新分配的临时变量即形参. 它的优点是避免了函数调用的一些副作用, 但 ...
- Unity3D-ScrollRect 各参数的代码引用以及作用
版本Unity4.6: 以下为ScrollRect面板上各选项 对应 在代码里的属性: content(RectTransform): scrollRect的RectTransform组件,即滑动面板 ...
- UGUI ScrollRect 各参数的代码引用以及作用
- php中引用&的真正理解-变量引用、函数引用、对象引用
php的引用(就是在变量或者函数.对象等前面加上&符号) //最重要就是 删除引用的变量 ,只是引用的变量访问不了,但是内容并没有销毁 在PHP 中引用的意思是:不同的名字访问同一个变量内容. ...
- PHP引用(&)使用详解
初学php关于&引用 官方文档: 1.引用是什么:http://www.php.net/manual/zh/language.references.whatare.php 2.引用做什么:ht ...
- php中关于引用(&)详解
php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...
- c++的引用
/*#include"iostream"using namespace std;void any_function(int & p);//声明函数any_function/ ...
随机推荐
- 车大棒浅谈for循环+canvas实现黑客帝国矩形阵
背景: 一日在网上闲逛的之时,突然看到一个利用JQ插件实现canvas实现的电影黑客帝国的小Demo.觉得创意不错,就下载下来研究一下. 网上浏览jQuery的写法 $(document).ready ...
- Bagging决策树:Random Forests
1. 前言 Random Forests (RF) 是由Breiman [1]提出的一类基于决策树CART的Bagging算法.论文 [5] 在121数据集上比较了179个分类器,效果最好的是RF,准 ...
- loadrunner controller:设置多个load generator
下面讲一下如何使用多台电脑进行负载测试. 1) 打开load generator,如图所示默认已添加了我们本地的Generator: 2) 点击"Add. ...
- C++ 头文件系列(forward_list)
简介 forwrad_list字面意思为前向列表,但实际上它是一种单向列表,只能从单一方向遍历. 单向链表实现 forward_list内部是用单向列表实现的,并且设计该库的时候就是以近乎手写的单向链 ...
- [C#]为微软ASP.NET官方教学视频增加字幕
前言 Microsoft Virtual Academy提供了学习ASP.NET的大量视频材料.(注1) 由于视频服务器位于海外,国内浏览速度并不理想,幸好官方提供了视频的下载地址以及英文字幕文件. ...
- JavaSE 教程的选择
你好 我是大福 你现在看的是大福笔记 又降温了 下点小雨 出门有点冷 走路到公司20多分钟,又走的有点热 昨天说到了,今年的计划是从零开始重新学习并梳理下这两年学习和接触到的技术 那么今天开始第一个知 ...
- UI进阶 即时通讯之XMPP登录、注册
1.XMPP环境搭建 http://www.cnblogs.com/fearlessyyp/p/5506644.html 第一次打开可能会有点儿慢,图片很多,步骤很详细,祝搭建成功. 2.工程中添加X ...
- vue自定义日期组件
vue-datepicker 基于 vuejs 2.x 可自定义主题的日期组件 github Usage 只需要在项目中加入 calendar.vue,就可以使用了. 向组件传入 prop 即可改变 ...
- c#类,接口,结构,抽象类介绍 以及抽象和接口的比较
c#中的类是最常见的实际上就是对某种类型的对象定义变量和方法的原型. 结构是值类型,而类是引用类型. 1.与类不同,结构的实例化可以不使用 new 运算符.结构可以声明构造函数,但它们必须带参数. 2 ...
- nodejs笔记2 --关于nodejs最新启动方式
1,运行应用以前是node app.js或者 supervisor app.js 2, 现在的应用方式是npm start或者supervisor bin/www