C++ 11 新特性 类型安全的空指针常量nullptr

C++11 引入的 nullptr 是一个专门用于表示空指针的关键字。

它的核心目的非常明确:彻底解决 C++98 中 NULL(本质是整数 0)带来的类型歧义问题,提供类型安全的空指针表示。

在 C++11 之前,我们用 NULL0 表示空指针,但它们在编译器眼里其实是整数。nullptr 的出现,让"空指针"终于有了属于自己的身份。

下面我将从语法、核心优势、底层机制及使用限制四个方面为你详细介绍。

1. 基本语法

nullptr 的用法非常简单,它可以直接赋值给任何指针类型。

cpp 复制代码
int* p1 = nullptr;      // 初始化 int 指针
char* p2 = nullptr;     // 初始化 char 指针
void* p3 = nullptr;     // 初始化 void 指针

// 它的类型是 std::nullptr_t (定义在 <cstddef> 中)
std::nullptr_t np = nullptr; 

2. 核心优势:为什么要用 nullptr

🛡️ 消除函数重载的歧义(最核心痛点)

在 C++98 中,NULL 通常被定义为 0。当你重载了一个接受 int 和一个接受 指针 的函数时,传入 NULL 会发生什么?编译器会优先匹配 int 版本,这往往违背了程序员的初衷。

  • C++98(歧义/错误):

    cpp 复制代码
    void func(int x) { cout << "调用了 int 版本" << endl; }
    void func(char* p) { cout << "调用了 指针版本" << endl; }
    
    func(NULL); // 输出:"调用了 int 版本" (因为 NULL 是 0)
    // 程序员本意是想传空指针,结果却调用了整数函数!
  • C++11(明确):

    cpp 复制代码
    func(nullptr); // 输出:"调用了 指针版本"
    // nullptr 只能转换为指针类型,编译器不再犹豫
🚫 类型安全:禁止转换为整数

nullptr 是一个纯指针概念,它不能隐式转换为整数类型。这防止了将空指针误用为数字的愚蠢错误。

cpp 复制代码
int x = nullptr; // ❌ 编译错误!
int y = NULL;    // ✅ 合法(但在现代 C++ 中不推荐),y 变为 0
🧩 模板推导更精准

在模板编程中,使用 NULL 会导致类型推导为 int,而 nullptr 能正确推导为指针类型或 std::nullptr_t

cpp 复制代码
template<typename T>
void printType(T t) { /* ... */ }

printType(NULL);    // T 被推导为 int
printType(nullptr); // T 被推导为 std::nullptr_t 或 指针类型

3. 底层机制:std::nullptr_t

nullptr 不是一个宏,也不是整数,它是一个字面量 ,其类型是 std::nullptr_t

  • 定义typedef decltype(nullptr) nullptr_t;
  • 转换规则std::nullptr_t 类型的值可以隐式转换为任何 原始指针类型(如 int*, void*)和成员指针类型。
  • 不转换 :它不能转换为整数类型。

4. 对比总结表

特性 0 NULL (C++98) nullptr (C++11)
本质类型 int int (通常是 0) std::nullptr_t
指针语义 模糊(既是数字也是指针) 模糊(宏定义,本质是数字) 明确(纯指针)
重载匹配 匹配 int 函数 匹配 int 函数 匹配 指针 函数
类型安全 低(可赋给 int) 低(可赋给 int) 高(不可赋给 int)
推荐程度 ❌ 绝不用于指针 ❌ 不推荐 唯一推荐

5. 避坑指南

  1. 不要混用 :在 C++11 及以后的代码中,永远不要再用 NULL ,全部替换为 nullptr

  2. 智能指针兼容nullptr 可以完美用于智能指针的初始化和重置。

    cpp 复制代码
    std::shared_ptr<int> sp = nullptr; // 合法
    sp = nullptr; // 合法,释放资源并置空
  3. 比较操作 :指针与 nullptr 的比较是安全的。

    cpp 复制代码
    if (p == nullptr) { ... } // 推荐写法
    if (!p) { ... }           // 也可以,但语义不如前者明确

一句话总结:
nullptr 是 C++ 类型安全的一块重要拼图。它用专用的类型 解决了通用的数字 0 带来的混乱。记住口诀:"指针为空用 nullptr,告别 NULL0!"

相关推荐
叼烟扛炮2 天前
C++第一讲:C++ 入门基础
开发语言·c++·函数重载·引用·内联函数·nullptr
小此方6 天前
Re:思考·重建·记录 现代C++ C++11篇 (四)C++ Lambda 全解析:编译器是如何为你生成仿函数的?
开发语言·c++·c++11·现代c++
结衣结衣.8 天前
手把手教你实现文档搜索引擎
linux·c++·搜索引擎·开源·c++11
2401_8920709811 天前
【C++11 后端实战】FixedThreadPool 固定线程池完整详解
c++11·生产者消费者·固定线程池
老四啊laosi14 天前
[C++进阶] 25. C++11新特性(一)
c++·c++11·右值
量子炒饭大师15 天前
【C++11】RAII 义体加装指南 ——【包装器 与 异常】C++11中什么是包装器?有哪些包装器?C++常见异常有哪些?(附带完整代码讲解)
开发语言·c++·c++11·异常·包装器
xiaoye-duck16 天前
【C++:C++11】C++11新特性深度解析:从类新功能、Lambda表达式到包装器实战
开发语言·c++·c++11
H Journey16 天前
C++11 新特性 万能函数容器之std::function
c++11·function·万能函数容器
xiaoye-duck19 天前
【C++:C++11】核心进阶:C++11引用折叠、完美转发与可变参数模板实战详解
开发语言·c++·c++11
xiaoye-duck20 天前
【C++:C++11】核心特性实战:详解C++11列表初始化、右值引用与移动语义
开发语言·c++·c++11