🦄个人主页:小米里的大麦-CSDN博客
🎏所属专栏:C++_小米里的大麦的博客-CSDN博客
🎁代码托管:C++: 探索C++编程精髓,打造高效代码仓库 (gitee.com)
⚙️操作环境:Visual Studio 2022
目录
1. 0 和空指针
2. NULL
3. nullptr
总结
共勉
在C/C++中,0
、NULL
和 nullptr
都表示指针的空值,但它们有不同的语义和使用场景。
1. 0
和空指针
在C和C++98中,数字 0
常常被用作空指针的表示。因为C语言规定整型常量 0
可以隐式转换为任意类型的指针值,所以使用 0
作为空指针值是合法的。
int* p1 = 0; // 合法,p1 是空指针
但是,使用 0
来表示空指针时,代码的可读性和可维护性较差,因为 0
既可以表示数值也可以表示指针。因此C++引入了 NULL
来代替 0
。
2. NULL
NULL
是在C语言的标准头文件 <stddef.h>
或 C++ 的 <cstddef>
中定义的宏,通常定义为 ((void*)0)
或单纯的 0
。在C++98中,它仍然可能会与整型 0
混淆,因为它本质上是 0
。
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else /* __cplusplus */
#define NULL ((void *)0)
#endif /* __cplusplus */
#endif /* NULL */
使用 NULL
来表示空指针可以提高代码的可读性,避免误将数字 0
和指针值混淆。 但因为 NULL
是宏,使用它仍然有一些潜在的问题,尤其是当函数重载涉及不同类型时。
#include <iostream>void Fun(int p) {std::cout << "Fun(int)" << std::endl;
}void Fun(int* p) {std::cout << "Fun(int*)" << std::endl;
}int main() {Fun(0); // 调用 Fun(int)Fun(NULL); // 调用 Fun(int) 因为 NULL 被定义为 0
}
在这个例子中,Fun(NULL) 实际上调用了 Fun(int),而不是期望的 Fun(int*),因为 NULL 被解释为 0。
3. nullptr
为了解决 0
和 NULL
的这些问题,C++11 引入了新的关键字 nullptr
,这是一个明确的空指针类型,可以确保它只能用于指针上下文中。
int* p1 = nullptr; // p1 是空指针
与 0
和 NULL
不同,nullptr
是类型安全的,不能被隐式转换为其他类型(如整型)。它不会产生函数重载歧义问题,因此推荐在C++11及之后的代码中使用 nullptr
。
#include <iostream>void Fun(int p) {std::cout << "Fun(int)" << std::endl;
}void Fun(int* p) {std::cout << "Fun(int*)" << std::endl;
}int main() {Fun(nullptr); // 明确调用 Fun(int*)
}
总结
虽然他们三者区别并不大,但是,在一些特殊情况还是需要进行区分使用的。
0
:C/C++98中,既可表示整数值,也可表示空指针,但可能产生混淆。NULL
:通过宏定义来表示空指针,虽然提高了可读性,但依然可能与整型0
混淆。nullptr
:C++11引入,明确表示空指针,解决了0
和NULL
的问题,推荐使用。
在现代C++中,优先使用 nullptr
来表示空指针,确保代码更安全和清晰。