【C++】C++的nullptr和NULL

在 C++ 中,nullptrNULL 都可以表示一个空指针(空地址),但它们的定义和用法存在显著差异。


1. NULL 是什么?

  • NULL 的定义:
    在 C 和早期的 C++ 中,NULL 通常被定义为整数 0,其定义如下(来自标准库 <cstddef><stddef.h>):
    #define NULL 0
    
  • 行为:
    • NULL 是一个预处理器宏,用来表示一个整数常量 0
    • 由于 NULL 被定义为 0,在某些上下文中可能会引发模糊性或类型问题。例如:
      void func(int);
      void func(void*);
      
      func(NULL); // 调用 func(int) 而不是 func(void*),因为 NULL 是 0(int 类型)。
      

2. nullptr 是什么?

  • nullptr 的定义:

    • nullptr 是在 C++11 引入的新关键字,表示空指针常量,它是一个专用的指针类型。
    • 它的类型是 std::nullptr_t,可以隐式转换为任何指针类型,但不能转换为整数类型。
  • 行为:

    • nullptr 是一种明确的空指针类型,避免了 NULL 带来的类型模糊问题。例如:
      void func(int);
      void func(void*);
      
      func(nullptr); // 明确调用 func(void*),因为 nullptr 是空指针类型。
      

3. 区别对比

特性NULLnullptr
引入版本C 和早期的 C++C++11
定义宏,通常定义为 #define NULL 0关键字,类型为 std::nullptr_t
类型整数常量,通常是 int专用类型 std::nullptr_t
指针转换可隐式转换为指针类型,但可能引起歧义可隐式转换为任何指针类型,无歧义
整数转换是一个整数,参与整数运算不是整数,不能参与整数运算
安全性易引起类型混淆,存在潜在的歧义问题类型安全,避免了指针和整数混淆的问题
适用性向后兼容的代码,旧式 C++ 项目现代 C++ 编程,推荐使用

4. **使用 **

  • 推荐使用 nullptr

    • nullptr 是类型安全的,不会与整数混淆。
    • 对于 C++11 及以上的代码,应始终使用 nullptr,它是现代 C++ 编程的标准。
  • 在旧代码中使用 NULL

    • 如果项目是混合 C 和 C++,或者使用了旧式代码,NULL 可能仍然会被使用。
    • 但在新开发中,应尽量避免使用 NULL,改用 nullptr

5. **示例 **

展示了 nullptrNULL 的不同效果:

#include <iostream>
using namespace std;

void func(int) {
    cout << "func(int) called" << endl;
}

void func(void*) {
    cout << "func(void*) called" << endl;
}

int main() {
    func(NULL);    // 输出:func(int) called,因为 NULL 是整数类型
    func(nullptr); // 输出:func(void*) called,因为 nullptr 是空指针类型

    // 类型检查
    int* p1 = NULL;       // 合法,NULL 转换为 int*
    // int val = nullptr; // 错误,nullptr 不能隐式转换为 int
    int* p2 = nullptr;    // 合法,nullptr 是类型安全的空指针

    return 0;
}
### C++ 链表中 `nullptr` `NULL` 的区别 在C++编程语言里,特别是在处理链表这样的数据结构时,`nullptr``NULL`都可以用来表示空指针的状态。然而,在现代C++实践中推荐使用`nullptr`而不是`NULL`。 #### 类型安全性差异 `NULL`本质上是一个宏定义,通常被设置为整数值0或者是`(void*)0`[^2]。这意味着它可以隐式地转换成几乎任何类型的值,这可能会引发意外的行为尤其是在模板代码或是重载函数调用的情况下。相反,`nullptr`是专门设计作为指向对象或函数的右值表达式的特殊关键字,仅能赋给指针变量,并且不会自动转为其他非指针类型的数据[^3]。 #### 可读性与维护便利性的考量 采用`nullptr`有助于提高程序的可读性清晰度。由于其明确代表了一个“无”的概念——即不存在有效的地址引用,因此对于阅读代码的人来说更加直观易懂。此外,当项目从较旧版本迁移到支持C++11特性的编译器环境时,统一替换所有的`NULL`为`nullptr`能够减少潜在错误并简化调试过程[^1]。 #### 实际应用中的表现 考虑如下简单的单向链表节点定义以及遍历逻辑: ```cpp struct ListNode { int val; ListNode* next; explicit ListNode(int x) : val(x), next(nullptr) {} // 使用 nullptr 初始化成员变量 }; // 假设 head 是某个已知的有效列表头部指针... for (ListNode *current = head; current != nullptr /* 或者 !current */ ; current = current->next){ std::cout << "Node value:" << current->val << '\n'; } ``` 在这个例子中,通过将新创建的对象的`next`字段显式初始化为`nullptr`,可以清楚表明该位置目前没有任何链接到下一个元素的信息;而在循环条件判断处也采用了同样的做法来终止迭代流程。如果这里改用`NULL`虽然也能工作,但在语义上不如前者那么精确[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值