细说引用和指针

来源:互联网 发布:大数据营销系统源码 编辑:程序博客网 时间:2024/06/05 20:54

[文献参考]

《C++ Primer (第4版)》Stanley B.Lippman 著 ——人民邮电出版社

《c++语言程序设计(第4版)》 郑莉 董源 何江舟 著——清华大学出版社

<C++程序设计教程(第二版)>》钱能著 ——清华大学出版社


   引用和指针有许多相似之处,例如它们都可以避免值复制的发生,从而减少函数调用时数据传递的开销。那么它们在深层中又有什么联系吗?

    在程序运行中,变量只能依靠地址来区别。因此,只有通过存储被引用变量的地址,在运行时才能准确定位被引用的变量。

    引用本身所占用的岑村空间中,存储的就是被引用变量的地址,这和指针变量所存储的内容具有相同的性质。

    指针式一种底层的机制,引用则是一种较高层的机制,在语言概念上引用是另一变量的“别名”,把地址这一概念隐藏起来了(所以对引用取地址获得的时被引用变量的地址,而非引用本身的地址)。它们的差异主要在语言形式上,实际上都是靠存储地址来实现的。

    引用与指针的显著区别是,普通指针可以被多次赋值,即是可以多次更改它所指向的对象,二引用只能在初始化时指定被引用的对象,去后不能更改,所以,引用的功能具有指针常量的性质。

下图为它们的对应关系:

操作T类型的指针常量对T类型的引用定义并用v初始化(v是T类型变量)T * const p = &v;T &r = v;取v的值*pr访问成员mp->mr.m读取v的地址p&r


可以肯定地说,能用引用实现的功能,用指针都可以实现。

既然这样,为什么还要引入引用这一概念呢?

指针是一种兼顾C语言特性的底层机制,正因为其底层,使用起来很灵活,功能强大。然而,正因为太过灵活,反而变得不好用。考虑一下情况:

①如果希望使用指针作为函数参数达到数据双向传递或减少传递开销的目的,在主调函数中需要用“&”传递参数,在被调用函数中需要用“*”访问数据,程序难免显得太过繁琐。

②编译器不会检查指针越界,有些情况下不需要指针的算术运算,这时如果对指针进行算术运算,会造成不必要的麻烦。

为了能够满足更加方便、安全的处理数据双向传递,减少参数传递开销这样的简单需求,引用这一概念被引入了C++中。

下面通过swap函数可比较指针和引用书写和使用上的繁简:

//使用指针常量 void swap(int * const pa, int * const pb){int temp = *pa;*pa = *pb;*pb = *pa;}int main(){int a, b;...swap(&a, &b);...return 0;}

//使用引用 void swap(int &ra, int &b){int temp = ra;ra = rb;rb = ra;}int main(){int a, b;...swap(a, b);...return 0;}


对于数据参数传递、减少大对象的参数传递开销这两个用途来说,引用可以很好的代替指针,使用引用比使用指针更加简洁、安全。


但有些时候,引用还不能完全替代指针,具体如下:

(1)如果一个指针所指向的对象,需要用分支结构加以确定,或者在中途需要改变它所指向的对象,那么在他初始化之后需要为它赋值,此时引用不能胜任。

(2)有时指针的值可能是一个空指针,空指针在一些情况下表达特定的含义,如ctime头文件中的time函数。

(3)使用指针函数,而没有函数引用。

(4)用new动态创建的对象或数组,需要用指针来存储它的地址。

(5)以数组形式传递大批量数据时,需要用指针类型接收参数。




原创粉丝点击