指针和引用
本片内容引用《c++程序语言设计》郑莉 董渊编著,不以盈利为目的。
指针和引用均可作为形参,都可以通过该参数修改主调函数中的变量以达到参数双向传递的目的,都可以避免值传递方式发生值复制从而减少函数调用时数据传递的开销。
引用介绍为其他变量的别名。但是对于一个确定的引用来说,它可能在不同的时候表示不同变量的别名,因此一定要在内存中为引用本身分配空间,来标识它所引用的变量。在程序运行时,变量只能依靠地址来区别,因此,只有通过存储被引用变量的地址,在运行时才能准确定位被引用的变量。引用本身所占用的内存空间中,存储的就是被引用变量的地址,这和指针变量所存储的内容具有相同的性质。引用功能和一级指针变量比较相近。
指针是C语言的灵魂,C++在继承了C语言指针的同时,引人了引用。指针存储的是地址,直接操作地址,所以说指针是一种底层的机制。引用则是一种较高层的机制,在语言概念上它是另一变量的“别名”,把地址这一概念隐藏起来了,但在引用运行时的实现机制中,还不得不借助于地址。二者可以说是殊途同归,差异主要是语言形式上的,最后都是靠存储地址来实现的。
普通指针可以多次被赋值,也就是说可以多次更改它所指向的对象,而引用只能在初始化时指定被引用的对象,其后就不能更改。因此,引用的功能,与一个指针常量差不多。
T = const p = &v; |||| T &r = v;
需要指出的是,虽然在“读取v的地址”这一用途上p和&r是等价的,但p和&r却具有不同的含义,p可以再被取地址,而&r则不行。也就是说,引用本
身(而非被引用的对象)的地址是不可以获得的,引用一经定义后,对它的全部行为,全是针对被引用对象的,而引用本身所占用的空间侧被完全隐藏起来了。因此,引用的功能还是要比指针常量略差一点。
注意 只有常引用,而没有引用常量,也就是说,不能用T & const作为引用类型。这是因为引用只能在初始化时指定它所引用的对象,其后则不能再更改,这使得引用本身(而非被引用的对象)已经具有常量性质了。
可以肯定地说,用引用能实现的功能,用指针都可以实现。那么C++为什么还要引入引用这一特性呢?
指针是一种底层机制,正因为其底层,所以使用起来很灵活,功能强大。然而,灵活不一定好用。例如,如果希望使用指针作为函数参数达到数据双向传递或减少传递开销的目的,则在主调函数中需要用“&”操作符传递参数,在被调函数中需要用“ * ”操作符来访问数据,程序会显得烦琐。而且在这类用途之下,指针的算术运算尽管不需要使用,但如果不慎被误用,则编译器并不会给出提示,这样会造成不必要的麻烦,指针的赋值运算亦是如此。虽然将指针设为常量可避免赋值运算被误用,但那又会使参数表变得烦琐,可读性降低。为了能够满足更加方便、安全地处理数据双向传递,减少参数传递开销这样的简单需求,C++对指针做了简单的包装,引入了引用。
对于数据参数传递、减少大对象的参数传递开销这两个用途来说,引用可以很好地代替指针,使用引用比指针更加简洁、安全。其中,如果仅仅是为了后一个目的,一般来说应当使用常引用作为参数。但有些时候,引用还是不能替代指针,这时还需要使用指针。这样的情况主要包括以下几种。
如果一个指针所指向的对象,需要用分支语句加以确定,或者在中途需要改变它所指向的对象,那么在它初始化之后需要为它赋值,而引用只能在初始化时指定
被引用的对象,所以不能胜任。
- 有时一个指针的值可能是空指针,例如当把指针作为函数的参数类型或返回类型时,有时会用空指针表达特定的含义(有兴趣的读者可以查看ctime头文件中的
- time函数),而没有空引用之说,这时引用不能胜任。
- 使用函数指针,由于没有函数引用,所以函数指针无法被引用替代。
- 用new动态创建的对象或数组,需要用指针来存储它的地址。
- 以数组形式传递大批量数据时,需要用指针类型接收参数.