引入
C语言中函数有两种传参的方式: 传值和传址。以传值方式, 在函数调用过程中会生成一份临时变量用形参代替, 最终把实参的值传递给新分配的临时变量即形参。 它的优点是避免了函数调用的副作用, 确无法改变形参的值。 如果要改变实参的值, 只 能通过指针传递。
1 void swap (int left, int right) 2 { 3 int temp = left; 4 left = right; 5 right = temp; 6 } 7 void swap (int *_pleft , int * _pRight) 8 { 9 assert (NULL ! = _pleft && NULL ! = _pRight) ; 10 int iTemp = * _pleft; 11 *_pleft = * _pRight; 12 *_pRight = iTemp;13 }
指针可以解决问题, 但不是很形象友好, 不安全, 因 此C++中 引 入了 一种新的符合类型--引用 。
引用概念
引用(reference)不是新定义一个变量, 而是给已存在的对象取了 一个别名 ,引用类型,引用另外一种类型。 编译器不会为引用对象新开辟内存空间, 它和它引用的对象共用同一块内存空间 。
1 int num = 110; 2 int &number = num; //number指向num(是num的另外一个名字)
一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时程序把引用和他的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成引用家将和他的初始对象一直绑定在一块。因为无法将引用重新绑定到另外一个对象上,因此引用必须初始化。
引用即别名
引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。定义一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的:
1 number = 120; //把120赋给number指向的对象,此处即是赋给了num 2 int tmp = number; //与tmp = num执行结果一样
为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以引用绑定的对象作为初始值。
引用的定义
允许在一条语句中定义多个引用,其中每个引用标识符都必须以&开头;
因为无法将引用重新绑定到另外一个对象上,因此引用必须初始化。
因为引用本身不是一一个对象,所以不能定义引用的引用。
一个变量可以有多个引用,而一个引用只能给一个变量对象 。
引用的类型要和与之绑定的对象严格匹配(不严谨)。
引用只能绑定在对象上而不能和字面值或某个表达式计算的记过绑定在一起。
1 int i1 = 10, i2 = 20 ; //i1和i2都是int型 2 int &r1 = i1, &r2 = i2; //r1和r2都是引用 3 int &r3 ; //报错:引用必须初始化 4 int &r4 = i1, &r5 = i2; //r1, r4同为i1的引用,r2, r5同为i2的引用 5 int &r4 = i2, &r5 = i1; //报错:r4不能同时分别为i1和i2的引用 6 int &r6 = 10; //报错:引用类型的初始值必须是一个对象 7 double i3 = 3.14; 8 int &r7 = i3; //报错:此处引用类型的初始值必须是int型对象
引用与指针
相同点:
底层的实现方式相同, 都是按照指针的方式来实现的:
不同点:
有空指针,没有空引用;
引用定义时必须初始化, 指针可以不用, 正常情况下需初始化为NULL;
引用一旦定义就不能再改变, 指针可以;
sizeof求取的值不一样;
自 ++含义不同;
可以有多级指针, 但是没有多级引 用;
指针和引用的地址不同;
int**/int&&意义不同;
总结:
1、 引 用在定义时必须初始化, 指针没有要求。
2、 一旦一个引 用被初始化为指向一个对象, 就不能再指向其他对象, 而指针可以在任何时候指向任何一个同类型对象。
3、 没有NULL引 用, 但有NULL指针。
4、 在sizeof中含义不同: 引 用结果为引 用类型的大小,但指针始终是地址空间所占字节个数。
5、 引 用自 加改变变量的内 容, 指针自 加改变了 指针指向。
6、 有多级指针, 但是没有多级引用。