引用(references)使用“.”操作符,指针(pointers)使用“*”和“->”操作符,这是两者最基本也是最熟悉的区别了,应该不用详说。
首先,没有所谓的null reference。一个reference必须总代表某个对象,因此C++要求references必须有初值:
string& rs;//错误!references必须被初始化
string s("xyzzy");
string& rs = s;//没问题,rs指向s
但是pointers就没有这样的限制,尽管有很大的风险:
string* ps;//未初始化的指针,有效,但风险高
虽然C++没有这样的限制,但是我们在声明一个指针的时候也最好要初始化,避免出现野指针。
下面这种情况也是不被允许的,要禁忌:
char* pc = 0;//将pointer设定为null
char& rc = *pc;//让references代表null pointer的解引值
这是有害的行为,其结果不可预测(C++)对此没有定义,编译器可以产生任何可能的输出。所以,
我们要永远不再考虑“reference称为null“的可能性。
上面的事实意味着使用reference可能会比使用pointer更富效率。这是因为使用reference之前不需要测试其有效性:
void printDouble(const duble& rd)
{
cout << rd;//不需要测试rd,它一定代表某个double
}
void printDouble(const double* pd)
{
if (pd)//检查是否为null pointer
{
cout << *pd;
}
}
其次,pointers和references之间的另一个重要的差异就是,pointers可以被重新赋值,指向另一个对象,references却总是指向(代表)它最初获得的那个对象:
string s1("Nancy");
string s2("Clancy");
string& rs = s1;//rs代表s1
string* ps = &s1;//ps代表s1
rs = s2;//rs仍然代表s1,但是s1的值现在变成了”Clancy“
ps = &s2;//ps现在指向s2,s1没有变化
还有其他情况也需要使用references,例如当你实现某些操作符的时候,最常见的例子就是operator[]。这个操作符很特别地必须返回某种”能顾被当做assignment赋值对象“的东西:
vector<int> v(10);//产生一个int vector,大小为10
v[5] = 10;//assignment的赋值对象是operator[]的返回值
因此,当知道需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由pointers达成,你就应该选择references。任何其他时候,请采用pointers。