收藏 分享(赏)

孙鑫VC++教程之第04节补充-引用.ppt

上传人:fmgc7290 文档编号:4839985 上传时间:2019-01-15 格式:PPT 页数:38 大小:215KB
下载 相关 举报
孙鑫VC++教程之第04节补充-引用.ppt_第1页
第1页 / 共38页
孙鑫VC++教程之第04节补充-引用.ppt_第2页
第2页 / 共38页
孙鑫VC++教程之第04节补充-引用.ppt_第3页
第3页 / 共38页
孙鑫VC++教程之第04节补充-引用.ppt_第4页
第4页 / 共38页
孙鑫VC++教程之第04节补充-引用.ppt_第5页
第5页 / 共38页
点击查看更多>>
资源描述

1、引用的扩展,引用和指针的区别引用的补充说明const &(const引用)数组的引用,引用和指针的区别,指针和引用主要有两个区别: 1.引用必须总是指向一个对象。 int *pi = NULL; 表示用NULL初始化pi,pi不指向任何对象。 const int ,引用和指针的区别,2.引用之间的赋值是另外一个不同,如果用一个引用给另一个引用赋值,那么改变的是被引用对象而不是引用本身。 int ival = 1024,ival2 = 2048; int *pi = 表示什么呢? pi指向的对象ival并没有改变。实际上pi被赋值为指向pi2所指向的对象,即ival2,现在pi和pi2指向同一个

2、对象。,引用和指针的区别,int ival = 1024,ival2 = 2048; int 表示什么?改变的是ival,而引用本身没有变化,赋值之后,两个引用仍然指向原来的对象。,引用和指针的区别,实际上c+很少独立的使用引用。引用主要用在函数的形参。bool GetNextValue(int ,引用的补充说明,#include #include using namespace std; void main(int argc,char* argv) int a=10; int b=20; int ,引用的补充说明,由于引用本身就是目标的一个别名,引用本身的地址是一个没有意义的值,所以在c+中

3、是无法取得引用的内存地址的。取引用的地址就是取目标的地址,c+本身就根本不提供获取引用内存地址的方法。 引用一旦初始化,就不在能够被指向其它的目标,虽然编译不会出错,但操作是不起作用的,实际上还是指向最先指向的目标。上面代码中的rn=b实际在计算机看来就是a=b,所以修改的还是a的值。,引用的补充说明,#include #include using namespace std; void main(int argc,char* argv) int a=10; void ,引用的补充说明,上面的两错误要记住引用的特性: void修饰是不能够声明引用的 引用是不能够声明数组的,即不能够声明引用数组

4、。为什么? 引用的一个重要的特性是,声明引用的同时要进行初始化,而数组元素的初始化方式对引用来说是没有意义的。,引用的补充说明(1),(1)全局返回变量值 float c; float test(float,float); void main(int argc,char* argv) float pn=test(3.0f,1.2f); coutpn; cin.get(); float test(float a,float b) c=a*b; return c; ,引用的补充说明,在上面的代码中我们可能以为函数返回的就是c变量。这么想可能就错了,普通情况下我们在函数内进行普通值返回的时候在内存栈

5、空间内其实是自动产生了一个临时变量temp,它是返回值的一个副本一个copy,函数在return的时候其实是return的这个临时产生的副本。,引用的补充说明,数据在内存中的情况如下图:,(2)下面我们再来看一种情况,就是把返回值赋给引用: #include #include using namespace std; float c; float test(float,float); void main(int argc,char* argv) float ,引用的补充说明,float 这句在bc中能够编译通过,因为bc扩展设置为临时变量设置引用,那么临时变量的生命周期将和引用的生命周期一致。

6、 但在vc中却不能通过编译,因为一但test()执行过后临时变量消失在栈空间内,这时候pn将成为一个没有明确目标的引用,会导致内存出错,引用的补充说明,它在内存中的情况见下图:,我们在图中看到,由于函数仍然是普通方法返回,所以仍然会有一个副本临时变量产生,只不过,这一次只是返回一个目标地址,在main中目标地址被赋予了引用pn。,下面我们再看一种情况,这是返回引用给变量的情况: #include #include using namespace std; float c; float ,引用的补充说明,这种返回引用给变量的情况下,在内存中,test()所在的栈空间内并没有产生临时变量,而是直接

7、将全局变量c的值给了变量pn,这种方式是我们最为推荐的操作方式,因为不产生临时变量直接赋值的方式可以节省内存空间提高效率,程序的可读性也是比较好的。,引用的补充说明,它在内存中的情况见下图:,最后的一种情况是函数返回引用,并且发值赋给一个引用的情况 #include #include using namespace std; float c; float ,引用的补充说明,这种情况同样也不产生临时变量,可读和性能都很好,但有一点容易弄错,就是当c是局部变量或者是在堆内存中临时开辟后来又被free掉了以后的区域,这种情况和返回的指针是局部指针的后果一样严重,会导致引用指向了一个不明确的地址,引用

8、的补充说明,在内存中情况见下图:,由于这种情况存在作用域的问题,故我们推荐采用第三种方式处理。,引用的补充说明,接下来我们说几个利用引用作为左值参与计算的例子,这一点一非常重要,对于理解返回引用的函数是非常有帮助的。,float c; float ,引用的补充说明,通常来说函数是不能作为左值,因为引用可以做为左值,所以返回引用的函数自然也就可以作为左值来计算了。 在上面的代码中:float 把函数作左值进行计算,这里由于test是返回引用的函数,其实返回值返回的地址就是c的地址,自然c的值就被修改成了12.1。,const &(const引用),const引用可以用不同类型的对象初始化(只要能

9、从一种类型转换到另一种类型即可),也可以是不可寻址的值,如文字常量,表达式值等。例如: double dval = 3.14; /仅仅对于cosnt才是合法的 const int ,const &(const引用),同样的初始化对于非const引用是不合法的,将导致编译错误。原因有些微妙,需要适当的做些解释。 引用在内部存放的是一个对象的地址,是该对象的别名。对于不可寻址的值,如文字常量,以及不同类型的对象,编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它。 double dval =1024; const int ,const &(const引用),如果我们给

10、ri赋值,不会改变dval的值,而是改变temp。对用户来说,修改动作没有生效,是没有意义的。因此使用const来进行约束,去除这种无意义的行为,因为const表示只读。不允许非const的引用指向需要临时对象的对象或者值。这比“允许定义这样的引用,但实际不会生效”的方案要好。,const &(const引用),下面我们通过一个例子来说明。 希望将一个引用初始化为一个const对象的地址。 const int ival = 1024;首先,我们知道非const引用定义是不合法的,将导致编译错误。 int /错误,要求一个const引用,const &(const引用),const int *,

11、const &(const引用),通过下面的对比,我们就可以更加明白为什么要用上面的方式表示了。 /声明一个指针const int ival = 1024;const int *pival = ,数组的引用,在C+中可以定义数组的引用,用以解决C中无法解决的“数组降阶”问题,我们先来看看什么是“数组降阶”,先看如下代码: void Test( char array20 ) cout sizeof(array) endl;/输出? char array20 = 0 ; cout sizeof(array) endl; /输出? Test( array );,数组的引用,我们看到,对于同样的数组a

12、rray,一个输出4,另一个输出20 。 这是因为void Test( char array20 ) 中的array被降阶处理了, void Test( char array20 ) 等同于 void Test( char array ) 也等同于 void Test( char* const array ) 如果你原意,它甚至等同于 void Test( char array999 ),数组的引用,也就是说 void Test( char array20 ) cout sizeof(array) endl; 被降成 void Test( char* const array ) cout si

13、zeof(array) endl; / 既然是char*,当然输出4 ,数组的引用,这样以来,我们在函数声明中的数组大小限制是无效的,声明 void Test( char array20 ) 并不能保证一定会接收到一个大小20的数组,即任何 char 都会被降价为 char* ,这样就增加了程序出错的可能性。要解决这样一个问题,我们可以用C+的数组引用作为参数,看以下代码:,数组的引用,void Test( char (,数组的引用,这样 Test 函数就只能接收大小为 20 的 char ,看如下代码: char array110 = 0 ; char array220 = 0 ; Test

14、(array1);/Error:实参不是大小为 10 的 char Test(array2);/OK,数组的引用,在 C+ 中,单纯的用数组的引用可以直接传递数组名,因为它将数组的大小已在形参里提供了信息。但是这样一来我们只能固定数组的大小来用这个函数了。用模板加数组的引用可以解决这个问题,看如下代码: template void Test(int (/OK,数组的引用,使用模板后确实可以使同一函数能够处理大小不同的数组了,扩大了函数的适用范围。但是这样定义的函数仍然存在着下述缺点: 1. 模板最终是要实例化的,所以调用多少个不同长度的数组,就要产生这个函数的多少份实例代码。而传统方式的函数只有一份实例,与函数的调用次数无关。 2. 不能应用于在编译期间数组的大小尚未确定的情况,这也使这个模板函数的适用范围受到限制。 3. 这样写的函数显然不能用指针变量作为函数的参数,因此不能用这个函数处理动态分配的内存区域。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 实用文档 > 简明教程

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报