c++ Pointers vs References


1.

Pointers References
int i; int i;
int *pi = &i; int &ri = i;
In both cases the situation is as follows:


Both pi and ri contain addresses that point to the location of i, but the difference lies in
the appearance between references and pointers when they are used in expressions.  In
order to assign a value of 4 to i in both cases, we write:
*pi = 4; ri = 4;
Note the, when using pointers, the address must be dereferenced using the *, whereas,
when using references, the address is dereferenced without using any operators at all!
The main effect of this is that the address can directly be manipulated if it is a pointer.
We can do things such as:
  pi++;
to increment to the next address.  This is not possible using references.  Therefore, to
summarize, a pointer can point to many different objects during its lifetime, a reference
can refer to only one object during its lifetime.


2.

引用的主要功能是传递函数的参数和返回值。 

C++语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递和引用传递。 

以下是"值传递"的示例程序。 

由于Func1函数体内的x是外部变量n的一份拷贝,改变x的值不会影响n, 所以n的值仍然是0。 
void Func1(int x) 

x = x + 10; 

... 
int n = 0; 
Func1(n); 
cout << "n = " << n << endl; // n = 0 

以下是"指针传递"的示例程序。 

由于Func2函数体内的x是指向外部变量n的指针,改变该指针的内容将导致n的值改变,所以n的值成为10。 
void Func2(int *x) 

(* x) = (* x) + 10; 

... 
int n = 0; 
Func2(&n); 
cout << "n = " << n << endl; // n = 10 

以下是"引用传递"的示例程序。 

由于Func3函数体内的x是外部变量n的引用,x和n是同一个东西,改变x等于改变n,所以n的值成为10。 
void Func3(int &x) 

x = x + 10; 

... 
int n = 0; 
Func3(n); 
cout << "n = " << n << endl; // n = 10 

continuing......


3. 一个具体的demo,转载:http://blog.csdn.net/andyzhange/article/details/336358

#include "stdafx.h"
#include <iostream>
using namespace std;


int main(int argc, char* argv[])
{
 int ival = 1024;
 int *pi  = &ival; // a pointer
 int &rval = ival; // a reference
 int jval = 4096;
 int xval = 8192;

 cout << "ival = " << ival << "/t";
 cout << "&ival = " << &ival << "/t";
 cout << endl;
 cout << "pi = " << pi << "/t";
 cout << "&pi = " << &pi << "/t";
 cout << "*pi = " << *pi << "/t";
 cout << endl;
 cout << "rval = " << rval << "/t";
 cout << "&rval = " << &rval << "/t";
 cout << endl;
 cout << "jval = " << jval << "/t";
 cout << "&jval = " << &jval << "/t";
 cout << endl;

 // change the values of the reference and the pointer
 pi = &jval;
 rval = jval;

 // print the changes
 cout << endl;
 cout << "ival = " << ival << "/t";
 cout << "&ival = " << &ival << "/t";
 cout << endl;
 cout << "pi = " << pi << "/t";
 cout << "&pi = " << &pi << "/t";
 cout << "*pi = " << *pi << "/t";
 cout << endl;
 cout << "rval = " << rval << "/t";
 cout << "&rval = " << &rval << "/t";
 cout << endl;
 cout << "jval = " << jval << "/t";
 cout << "&jval = " << &jval << "/t";
 cout << endl;

 cout << endl;
 *pi = xval;
 cout << "pi = " << pi << "/t";
 cout << "&pi = " << &pi << "/t";
 cout << "*pi = " << *pi << "/t";
 cout << endl;
 cout << "jval = " << jval << "/t";
 cout << "&jval = " << &jval << "/t";
 cout << endl;

 return 0;
}

一次的执行结果如下:
ival = 1024     &ival = 0012FF7C
pi = 0012FF7C   &pi = 0012FF78  *pi = 1024
rval = 1024     &rval = 0012FF7C
jval = 4096     &jval = 0012FF70

ival = 4096     &ival = 0012FF7C
pi = 0012FF70   &pi = 0012FF78  *pi = 4096
rval = 4096     &rval = 0012FF7C
jval = 4096     &jval = 0012FF70

pi = 0012FF70   &pi = 0012FF78  *pi = 8192
jval = 8192     &jval = 0012FF70


4. Reference 在运算符重载上的运用,转载: http://www.cnblogs.com/whyandinside/archive/2010/07/18/1780185.html

   

enum day{
Sunday, Monday, …
};
day x;

表达式 ++x 不能编译。如果想让它通过编译,必须要定义一个名为operator++的函数,接受day为参数,并且调用 ++x 必须改变x的值。因此, 仅声明一个函数 operator++ , 以类型day为参数, 如下:
day operator++(day d);
并不能够得到想要得效果。 这个函数通过值传递参数(pass by value),这就意味着函数内看到的是参数的一个拷贝,而不是参数本身。为了使函数能够改变其操作数(operand)的值,它必须通过指针或 reference来传递其操作数。通过指针传递参数(passing by pointer),函数定义如下:
day *operator++(day *d);
它通过将增加后的值存储到*d里面来使函数改变日期(day)的值。但是,这样你就必须使用像表达式++&x这样来调用这个操作符,这看起来不太对劲儿。正确的方法是定义operator++以reference为参数类型,如下:

day &operator++(day &d)
{
d = (day)(d + 1);
return d;
}

使用这个函数, 表达式 ++x 才有正确的显示以及正确的操作。

Passing by reference不仅仅是写operator++较好的方法,而是唯一的方法。 C++在这里并没有给我们选择的余地。 像下面的声明:
day *operator++(day *d);
是不能通过编译的。每个重载的操作符函数必须或者是一个类的成员, 或者使用类型T、 T & 或 T const & 为参数类型,这里T是一个类(class)或列举(enumeration)类型。也就是说,每一个重载操作符必须以类或列举类型为参数类型。指针,即使是指向一个类或列举类型对象的指针,也不可以用。C++ 不允许在重载操作符时重新定义内置操作符的含义,包括指针类型。因此,我们不可以定义:
int operator++(int i); // 错误
因为它试图对int重新定义操作符 ++ 的含义。 我们也不可以定义:
int *operator++(int *i); // 错误
因为它试图对 int * 重新定义操作符 ++ 的含义。

    

5. 安全性的考虑  

有些人认为既然reference不能够为空,那么它应该比指针更安全。我认为reference可能要安全一点,但不会安全很多。虽然一个有效的reference不能为空,但是无效的可以呀。实际上,在很多情况下程序有可能产生无效的reference,而不只是空的reference。例如,你可以定义一个reference,使它绑定到一个指针指向的对象,如下所示:

int *p;

int &r = *p;

如果指针*p在reference定义时刚好为空,则这个reference为空。从技术上来说,这个错误并不在于将reference绑定到一个空值,而是在于对一个空指针去参考。对一个空指针去参考产生了一个不确定的操作,也就意味着很多事都可能发生,而且大部分都不是什么好事。很有可能当程序将 reference r 绑定到*p (p所指向的对象)的时候,p实际上没有被去参考,甚至程序只是将p的值拷贝给实现r的指针。而程序将会继续执行下去直到错误在后面的运行中更为明显的表现出来,产生不可预知的危害。

下面的函数展示了另外一种产生无效reference的方法:

int &f()
{
int i;

return i;
}

这个函数返回一个指向本地变量 i 的reference。然而当函数返回时,本地变量 i 的存储空间也就消失了。因此这个函数实际返回了一个指向被回收了的空间的reference。这个操作与返回一个指向本地变量的指针的后果相同。有些编译器可以在编译时发现这个错误,但也很有可能不会发现。

我喜欢reference,也有很好的理由使用它们代替pointer。但如果你期望使用reference来使你的程序健壮性显著增强,那么你多半会失望的。


6.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值