条款一:指针与引用的区别
指针与引用看上去完全不同(指针用操作符’*’和’->’,引用使用操作符’.’),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。
问题:你如何决定在什么时候使用指针,在什么时候使用引用呢?
区别1:引用必须初始化(现代编译器会进行检查),而指针不用强求,虽然不初始化会带来安全隐患。
注:不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。
void printDouble(const double& rd)
{
cout << rd; // 不需要测试rd,它
} // 肯定指向一个double值
相反,指针则应该总是被测试,防止其为空
void printDouble(const double *pd)
{
if (pd)
{// 检查是否为NULL
cout << *pd;
}
}
区别2:指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变。注1[具体是说不能改变指向]
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 没有改变
注:不是说引用不能被改变吗?为什么例子中可以被重新赋值?
准确理解引用<==>const类型的指针,这样就明白了为什么以及解释为什么必须要初始化
使用引用的场合:
有一种情况,就是当你重载某个操作符时,你应该使用引用。最普通的例子是操作符[]。这个操作符典型的用法是返回一个目标对象,其能被赋值。
vector<int> v(10); //建立整形向量(vector),大小为10
//向量是一个在标准C库中的一个模板(见条款35)
v[5] = 10; // 这个被赋值的目标对象就是操作符[]返回的值
如果操作符[]返回一个指针,那么后一个语句就得这样写:
*v[5] = 10;
但是这样会使得v看上去象是一个向量指针。因此你会选择让操作符返回一个引用。(这有一个有趣的例外,参见条款30)
总结:两种情况使用引用,其它情况考虑使用指针
1.当你知道你必须指向一个对象并且不想改变其指向时
2.在重载操作符并为防止不必要的语义误解时,例如操作符[]。