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!"

相关推荐
weixin_4617694017 小时前
通过数组和队列构造二叉树方法(用于算法测试),C++ vector不能直接使用null
数据结构·c++·算法·vector·nullptr·null
handler015 天前
【C++11 】Lambda 表达式、std::function 与 std::bind 解析
c++·c·c++11·bind·解耦·function·lamda
Irissgwe10 天前
c++11(lambda表达式与包装器、线程库)
c++·c++11·lambda表达式·线程库·包装器·互斥量库·条件变量库
繁华落尽,倾城殇?11 天前
[C++11] : atomic,nullptr,default/delete,enum class
开发语言·c++·c++11·nullptr·atomic·enum class·default/delete
BestOrNothing_201512 天前
C++零基础到工程实战(5.2.5):函数默认参数和函数重载
c++·函数重载·函数默认参数·nullptr·函数声明与定义
拾光Ծ12 天前
C++11实用的新特性:lambda表达式与包装器function与bind
c++·c++11·lambda·bind·function·函数包装器
咩咦23 天前
C++学习笔记10:auto关键字
c++·学习笔记·c++11·auto·类型推导
进击的荆棘23 天前
C++起始之路——C++11(下)
开发语言·c++·c++11·lambda
fffzd1 个月前
C++入门(二)
开发语言·c++·算法·函数重载·引用·inline内联函数·nullptr
小此方1 个月前
Re:思考·重建·记录 现代C++ C++11篇(六) 从 shared_ptr 到 weak_ptr:起底智能指针的引用计数与循环引用之痛
开发语言·c++·c++11·现代c++