1.指针可以被多次绑定,而引用不能
引用跟一个对象绑定后,直到那个对象生命周期结束,都不能绑定到其他对象。
看这么一个例子:
int i= 2;
int j = 4;
int &ri = i;
ri = j;
j = 8;
通过结果可知,此时i=ri=4,说明ri并没有绑定到j上,而刚才ri=j只是简单的赋值操作,虽然在vs下能顺利编译通过。
因此引用变量是从一而终的,因此必须在声明时就确定引用的对象。
2.引用不一定都是安全的
可能有人会觉得既然引用变量不能为空或是NULL,是不是引用就比指针就安全得多呢。大多数情况下是的,但也没想象中的那么安全,因为我们还是有很多种办法可以使它空引用。看下面的一个例子
int *pi;
int &ri=*pi;
3.引用变量&到底是什么
引用一开始学习C++时很经典的一个例子
//通过引用方式传递的是真真切切的对象,既不是对象的拷贝也不是对象的地址
void swap_reference(int &v1, int &v2){
int temp = v1;
v1 = v2;
v2 = temp;
}
//swap_pointer(v1, v2)由于是对地址的操作,可以达到互换的目的
void swap_pointer(int *v1, int *v2){
int temp = *v1;
*v1 = *v2;
*v2 = temp;
}
//swap函数时,互换的是函数空间内的两个值,可认为是v1,v2的两个拷贝互换了
void swap(int v1, int v2){
nt temp = v1;
v1 = v2;
v2 = temp;
}
可以认为,变量a和变量c就是同一个变量,因为二者的值、址,以及在程序中的作用方式完全一致,因此在C++ Primer中说“引用变量就是变量的别名”。但不同之处在于,引用变量要有初始化过程。
intmain(){
inta=1;
cout<<"普通变量:"<<"值:"<<a<<" 址:"<<&a<<endl;
int*b=&a;
cout<<"指针变量:"<<"值:"<<b<<" 址:"<<&b<<endl;
int&c=a;
cout<<"引用变量:"<<"值:"<<a<<" 址:"<<&c<<endl;
return0;
}
普通变量:值:1址:0x6dfef8
指针变量:值:0x6dfef8址:0x6dfef4
引用变量:值:1址:0x6dfef8
这里做一下总结:变量对应着某个存储单元,具有地址和值。对普通变量的访问,访问的是它的值;而对指针变量的访问(*操作),访问的是它所指向的变量的值;引用变量就是变量别名。此外,我们说普通变量和指针作为函数参数时,是传值,而引用变量才是传址。所谓传值,是指改变形参变量的内容,而传址,是指改变形参变量的地址,也就是改变它所对应的存储单元。指针寻址方式,对于计算机实现来说很容易,但对于人理解却不太容易。这可能是Java中不采用指针的原因之一吧,但实际上Java中的引用就是C++中的指针,遗憾的是,Java中没有C++中的指针,在一些情况下会使得代码比较复杂。
实例算法:
示例:
#include <iostream>
using namespace std;
int main(){
int var; // 声明int类型变量var
int * ptr; // 声明指针变量ptr
ptr = &var; // 先使用 & 运算符获取变量var的地址,再把该地址赋值给指针变量ptr
int ** pptr; // 声明二级指针变量pptr
pptr = &ptr; // 先使用 & 运算符获取变量ptr的地址,再把该地址赋值给二级指针变量pptr
int & ref1 = var; // 声明引用变量ref1, ref1是变量var的别名(引用必须在创建时被初始化)
int & ref2 = *ptr; // 先使用*运算符获取指针变量ptr所指向的变量(即var),再用该变量(var)初始化引用变量ref2(声明引用变量ref2的同时对它进行初始化)。也就是说,该行代码执行后,ref2也是变量var的别名 var = 20
cout << "Value of var: ";
cout << var << endl;
cout << "Value of &var: ";
cout << &var << "\t(var的地址)" << endl;
cout << endl;
cout << "Value of ptr: ";
cout << ptr << "\t(等于&var)" << endl;
cout << "Value of *ptr: ";
cout << *ptr << "\t\t(等于var)" << endl;
cout << "Value of &ptr: ";
cout << &ptr << "\t(ptr的地址)" << endl;
cout << endl;
cout << "Value of pptr: ";
cout << pptr << "\t(等于&ptr)" << endl;
cout << "Value of *pptr: ";
cout << *pptr << "\t(等于ptr, 等于&var)" << endl;
cout << "Value of **pptr: ";
cout << **pptr << "\t\t(等于*ptr, 等于var)" << endl;
cout << "Value of &pptr: ";
cout << &pptr << "\t(pptr的地址)" << endl;
cout << endl;
cout << "Value of ref1: ";
cout << ref1 << "\t\t(等于var)" << endl;
cout << "Value of &ref1: ";
cout << &ref1 << "\t(等于&var)" << endl;
cout << endl;
cout << "Value of ref2: ";
cout << ref2 << "\t\t(等于var)" << endl;
cout << "Value of &ref2: ";
cout << &ref2 << "\t(等于&var)" << endl;
return 0; }
输出结果:
Value of var: 20
Value of &var: 0x7ffce63490bc (var的地址)
Value of ptr: 0x7ffce63490bc (等于&var)
Value of *ptr: 20 (等于var)
Value of &ptr: 0x7ffce63490b0 (ptr的地址)
Value of pptr: 0x7ffce63490b0 (等于&ptr)
Value of *pptr: 0x7ffce63490bc (等于ptr, 等于&var)
Value of **pptr: 20 (等于*ptr, 等于var)
Value of &pptr: 0x7ffce63490a8 (pptr的地址)
Value of ref1: 20 (等于var)
Value of &ref1: 0x7ffce63490bc (等于&var)
Value of ref2: 20 (等于var)
Value of &ref2: 0x7ffce63490bc (等于&var)