前言:
`nullptr` 是 C++11 引入的一个新特性,它是一种特殊类型的常量,用于表示空指针。在 C++11 之前,我们通常使用 `NULL` 或 `0` 来表示空指针。本章列举了 `nullptr` 相对于 `NULL` 的几个主要优势:
1. 类型安全
- `nullptr` 是 `std::nullptr_t` 类型,它可以隐式转换为所有原始指针类型,但不能转换为其它类型,这提供了更好的类型安全。
- `NULL` 实际上是一个整数(通常定义为 `#define NULL 0`),因此,它可以赋值给任何整数类型,导致类型安全问题。
int *p = nullptr; // 合法
int n = nullptr; // 不合法
int *q = NULL; // 合法,但不安全
int m = NULL; // 合法,但可能不是你想要的
2. 函数重载
由于 `nullptr` 是一个特定类型的指针,而 `NULL` 实际上是一个整数,因此在函数重载中,使用 `nullptr` 可以避免一些歧义和错误。
void f(int) {
cout << "f(int) called" << endl;
}
void f(char*) {
cout << "f(char*) called" << endl;
}
int main() {
f(NULL); // 调用 f(int)
f(nullptr); // 调用 f(char*)
}
在上面例子中,如果使用NULL,会调用f(int)
,这可能不是程序员预期的行为;而nullptr会正确地调用f(char*)
。
3. 易读性和表达意图
`nullptr` 更清晰地表示“空指针”的概念,增加了代码的可读性,并更准确地表达了程序员的意图。
if(p == nullptr) // 更清晰地表达了 p 是一个指针
nullptr提供了一种清晰、一致的方式来表示空指针,它不同于整数0或者NULL。这可以帮助开发者写出更易理解和维护的代码。
4. 模板和类型推导
在模板代码和自动类型推导的场景中,`nullptr` 的类型安全特性特别有用。
template<typename T>
void foo(T ptr) {
// ...
}
foo(nullptr); // T 被推导为 std::nullptr_t
foo(NULL); // T 被推导为 int,可能导致错误或不期望的行为
5. 对成员函数指针的支持
`nullptr` 可以赋值给成员函数指针,而 `NULL` 或 `0` 则不能直接用于赋值。
class MyClass {
public:
void memberFunction() {}
};
void (MyClass::* memberFunctionPtr)() = nullptr; // 合法
void (MyClass::* memberFunctionPtr2)() = NULL; // 非法,需要进行类型转换
6. 对数组的支持
nullptr还能更好地支持数组,不会出现将NULL赋值给指针数组时的潜在问题。
示例:
int* arr[10] = {nullptr}; // All elements are initialized to nullptr
如果使用NULL来初始化指针数组,可能会因为类型转换而引发一些不容易察觉的问题。
使用 `nullptr` 替代 `NULL` 可以获得更好的类型安全、清晰的语义和更准确的类型推导,在现代 C++ 编程中,推荐使用 `nullptr` 来表示空指针。
总结:
C++11中的nullptr通过提供明确的类型和语义,解决了使用NULL可能出现的类型不安全和语义不清的问题。它在函数重载、模板编程以及代码的可读性和可维护性方面,相较于NULL都表现出了显著的优势。
综上,建议使用nullptr来代替NULL。