"More Effective C++"
在C++编程中,`指针`和`引用`是两种重要的概念,它们提供了间接访问其他对象的方式。然而,它们之间存在显著的差异,选择何时使用哪种取决于具体的设计需求和场景。下面将详细讨论这两个特性。
首先,`指针`可以被设置为`NULL`或`nullptr`,表示它不指向任何对象。这在某些情况下是必要的,比如当变量在某个阶段可能不需要指向特定对象时。你可以通过赋值`NULL`或`nullptr`来解除指针的关联。然而,`引用`是不同的,它一旦被初始化,就必须始终引用一个有效的对象,不能为`NULL`。这意味着,如果在设计中允许变量不指向任何对象,那么应该使用指针,以便可以将它设为空值。
尝试让引用`引用空值`是不安全的,如示例所示:
```cpp
char *pc = 0; // 设置指针为空值
char &rc = *pc; // 让引用指向空值,这是非常有害的
```
这段代码会导致未定义的行为,因为引用必须始终引用一个对象。在C++中,引用必须在声明时初始化,不能留作未初始化状态:
```cpp
string &rs; // 错误:引用必须被初始化
```
另一方面,`引用`的一个优点是它们的隐含安全性。由于引用总是有效,所以在使用引用时不需要像检查指针是否为`NULL`那样进行额外的验证:
```cpp
void printDouble(const double &rd) {
cout << rd; // 不需要测试rd,它肯定指向一个double值
}
```
而使用指针时,则需要进行空指针检查:
```cpp
void printDouble(const double *pd) {
if (pd) { // 检查是否为NULL
cout << *pd;
}
}
```
此外,`指针`可以被重新赋值,指向不同的对象,而`引用`一旦初始化后,就不能改变其引用的对象:
```cpp
string s1("Nancy");
string s2("Clancy");
string &rs = s1; // rs引用s1
string *ps = &s1; // ps指向s1
rs = s2; // rs仍旧引用s1,但s1的值现在是"Clancy"
```
在这里,`rs`的引用并没有改变,而是`s1`的内容被更新为了`s2`的内容。相反,`ps`可以通过`ps = &s2;`来改变指向。
总结来说,选择使用`指针`还是`引用`取决于以下几点:
1. 是否允许变量在某些时刻不指向任何对象(使用指针)。
2. 是否需要在程序运行时改变变量所指向的对象(使用指针)。
3. 是否想要提高代码的安全性和效率,减少空指针异常(使用引用)。
4. 初始化的要求,引用必须在声明时初始化,而指针可以在声明后任何时候初始化。
在编写C++代码时,理解这些区别并明智地选择使用哪种类型,可以提高代码的可靠性和可维护性。