指针变量和引用变量的区别



  1. 最近在逛StackOverflow,有个人问了一个很好的问题“What are the differences between a pointer variable and a reference variable in C++“,因为在C++中,引用和指针都发挥着类似的功能,虽然我们都有着天然的直觉,在某个地方就只能用指针而不能用引用,就像以前做英语单选一样,总觉得这个空的答案是XXX,却说不出个所以然来。这就是我要写这篇博客的目的,尽可能地总结出这两者之间的区别,囿于水平,错误以及不足之处欢迎指正。
    调试机器:VS2012
    环境:Win8.1 32位系统
    Stack Overflow

指针可以被多次绑定,而引用不能

引用跟一个对象绑定后,直到那个对象生命周期结束,都不能绑定到其他对象。
看这么一个例子:

int i= 2;
int j = 4;
int &ri = i;
ri = j;
j = 8;

此时i=ri=4,说明ri并没有绑定到j上,而刚才ri=j只是简单的赋值操作,虽然在vs下能顺利编译通过。
看一下下面的例子

int *const p = &i;
p = &j;//error

p在赋值j时出现错误,那是因为常数指针在代码中是不能进行赋值或是绑定操作的,所以在常数指针的声明时,必须要给他赋值,否则会报错。

int *const p;//error

这一点跟引用变量具有不能重复绑定的性质很相像,所以引用变量也像常数指针一样在声明时,不能声明一个空的引用。 但是也不完全的一样,例如声明对象是NULL时,两者就会出现差异。

int *const pi = NULL//ok
int &ri = NULL;//error

引用不一定都是安全的

可能有人会觉得既然引用变量不能为空或是NULL,是不是引用就比指针就安全得多呢。大多数情况下是的,但也没想象中的那么安全,因为我们还是有很多种办法可以使它空引用。看下面的一个例子

int *pi;
int &ri=*pi;

声明了一个空指针pi,引用变量ri此时恰好引用pi指针,这种情况在vs2012下是可以编译通过的,但是很明显在调用时会发生错误。再看另一个例子:

int &f(){
    int i ;
    return i;
}

函数f的返回值类型为int &,但是局部变量i的栈空间在函数结束后也一并摧毁,此时它指向了一个未知空间或是未知数。
并没有绝对安全的技术,良好的编程习惯可以帮助我们克服很多这一类的问题。

引用变量&到底是什么

引用一开始学习C++时很经典的一个例子

void swap_reference(int &v1, int &v2){
    int temp = v1;
    v1 = v2;
    v2 = temp;
}
void swap_pointer(int *v1, int *v2){
    int temp = *v1;
    *v1 = *v2;
    *v2 = temp;
}
void swap(int v1, int v2){
    nt temp = v1;
    v1 = v2;
    v2 = temp;
}

我们知道swap(v1,v2)并不能做到两个值的交换,这是因为在执行swap函数时,互换的是函数空间内的两个值,可认为是v1,v2的两个拷贝互换了。swap_pointer(v1, v2)由于是对地址的操作,可以达到互换的目的。我们也知道swap_reference(v1,v2)也可以执行这样的目的,不同于以上的两种方式,通过引用方式传递的是真真切切的对象,既不是对象的拷贝也不是对象的地址。一个很有趣的例子

char i = 'a';
char b='9';
char *pi = &i;
char &ri = b;
cout<<sizeof(ri)<<endl;
cout<<sizeof(*pi)<<endl;
cout<<sizeof(&ri)<<endl;
cout<<sizeof(pi)<<endl;
cout<<(void*)&ri<<"\n"<<(void*)&b;

在栈里创建了一个char型的指针和引用,结果用sizeof计算大小时输出1144,而且ri和b的地址一样,ri和b的值也一样,看起来引用是原对象的一个nick name。但问题来了,我在声明了一个引用变量ri,这个变量的地址确是b地址,系统没有给ri分配栈空间,这听起来真的很不可思议。
还有一个很有趣的事情,如果我们稍微改下输出,发现这两个输出值会不一样。

char b[2]={'9'};
cout<<(void*)(&b+1)<<"\n"<<(void*)(b+1);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值