第 18.2 節

nullptr

0瀏覽次數0訪問次數--跳出率--平均停留

What problem does this section solve?

In traditional C/C++, NULL or 0 is used to represent a null pointer. However, this presents a problem:

  • NULL is actually 0 (defined as #define NULL 0 in C++) and is treated as an integer, leading to a type mismatch.
  • In some overloaded functions, NULL may match the integer version of the function rather than the pointer version.

nullptr is the true "void pointer type," resolving these type safety issues.

What is this feature?

nullptr is a keyword introduced in C++11, its type is std::nullptr_t, it can be implicitly converted to a pointer of any type, but it cannot be implicitly converted to an integer type. This allows the compiler to distinguish between a "null pointer" and "integer 0".

C++ standard version

C++11

Required header files

No additional header files are required. nullptr is a language keyword. If you need to use the std::nullptr_t type, you must include #include <cstddef>.

Basic Syntax

int* p = nullptr;           // 空 int 指针
double* d = nullptr;        // 空 double 指针
std::shared_ptr<int> sp = nullptr;  // 空智能指针

// 判断空指针
if (p == nullptr) { ... }
if (!p) { ... }             // 等价写法
if (p) { ... }              // p 非空

Common Usage

UsageExplanation
int* p = nullptr;initialize null pointer
p == nullptrCheck if it is nullptr.
if (ptr)Check if not null
func(nullptr)Passing a null pointer argument
return nullptr;Return a null pointer.

The Difference Between nullptr and Other "Null" Values

nullptr only represents a "pointer that points to no object." It is not the integer 0, nor an empty string, and certainly not an empty container.

The phrase "表达含义" translates to "express meaning" or "convey the meaning".Recommended Writing StyleDon't mix
null pointerT* p = nullptr;Understood. I will keep the placeholders NULL and 0 exactly as they are in the translation.
empty smart pointerstd::shared_ptr<T> p = nullptr;Avoid manually using new/delete.
empty stringstd::string s; or ""Do not use nullptr.
may not return a valuestd::optional<T>Don't force a 'special value' into it.
Container is emptyv.empty()Don't confuse it with checking if a pointer is null.

Example code

Example 1: Basic Usage of nullptr

#include <iostream>
#include <cstddef>

int main()
{
    int* p1 = nullptr;    // 空指针初始化
    int* p2 = 0;           // 旧写法(用 0 赋给指针)
    int* p3 = NULL;        // 旧写法(NULL 实际上还是 0)

    // 三种写法在简单的场景下等价
    std::cout << "p1 = " << p1 << "\n";
    std::cout << "p2 = " << p2 << "\n";
    std::cout << "p3 = " << p3 << "\n";

    // 判断空指针
    if (p1 == nullptr)
    {
        std::cout << "p1 is null\n";
    }

    return 0;
}

Results

p1 = 0
p2 = 0
p3 = 0
p1 is null

Example 2: Builds on Example 1 to show how nullptr resolves overload ambiguity.

#include <iostream>

// 两个重载函数
void process(int n)
{
    std::cout << "process(int): " << n << "\n";
}

void process(int* p)
{
    if (p == nullptr)
    {
        std::cout << "process(int*): nullptr\n";
    }
    else
    {
        std::cout << "process(int*): " << *p << "\n";
    }
}

int main()
{
    process(42);        // 调用 process(int)
    process(nullptr);   // 调用 process(int*),明确是指针版本

    // process(NULL);   // ❌ 有歧义!编译器不知道调哪个
    // process(0);      // ❌ 同样的问题!0 匹配 process(int)

    int* p = nullptr;
    process(p);         // 调用 process(int*)

    return 0;
}

Results

process(int): 42
process(int*): nullptr
process(int*): nullptr

Example 3: Building on Example 2, the application of nullptr in templates and smart pointers

#include <iostream>
#include <memory>

template <typename T>
void check_ptr(T* ptr)
{
    if (ptr == nullptr)
    {
        std::cout << "pointer is null\n";
    }
    else
    {
        std::cout << "pointer value = " << *ptr << "\n";
    }
}

int main()
{
    // 原始指针初始化为空
    int* rp = nullptr;
    check_ptr(rp);

    // 智能指针初始化为空
    std::shared_ptr<int> sp = nullptr;
    // 智能指针也可直接用 bool 判断
    if (!sp)
    {
        std::cout << "shared_ptr is null\n";
    }

    // 创建后赋值
    sp = std::make_shared<int>(100);
    if (sp)
    {
        std::cout << "shared_ptr value = " << *sp << "\n";
    }

    return 0;
}

Results

pointer is null
shared_ptr is null
shared_ptr value = 100

Example 4: nullptr is not magic—multiple pointer overloads still require specifying the type

#include <iostream>

void reset(int* p)
{
    std::cout << "reset int pointer\n";
    if (p != nullptr)
    {
        *p = 0;
    }
}

void reset(double* p)
{
    std::cout << "reset double pointer\n";
    if (p != nullptr)
    {
        *p = 0.0;
    }
}

int main()
{
    int count = 42;
    double ratio = 3.14;

    reset(&count);   // 明确调用 int* 版本
    reset(&ratio);   // 明确调用 double* 版本

    int* count_ptr = nullptr;
    reset(count_ptr); // 仍然明确是 int* 版本

    // reset(nullptr); // ❌ 编译错误:nullptr 可以转成 int*,也可以转成 double*

    std::cout << "count = " << count << "\n";
    std::cout << "ratio = " << ratio << "\n";

    return 0;
}

Results

reset int pointer
reset double pointer
reset int pointer
count = 0
ratio = 0

runtime results

See the "running results" for each example above.

Key syntax explanation in the example

|Here is the translation of the provided Simplified Chinese Markdown fragment into natural American English, following all specified rules.


ExampleDiscusses whatNewly emerged syntaxWhy write it this wayPrecautions
Example 1Basic usage of nullptrnullptrp == nullptrInitialize the pointer to "NULL", type-safeThe type of nullptr is std::nullptr_t
Example 2Resolve overload ambiguityHow nullptr matches the pointer version in overloaded functionsNULL cannot distinguish between integer and pointer overloading, but nullptr can.This is why nullptr is used instead of NULL.
Example 3Templates and Smart Pointersshared_ptr = nullptrif(sp)Smart pointers can also be initialized with nullptr.The bool conversion of smart pointers is equivalent to != nullptr
Example 4Multiple pointer overloadingint*double*nullptrnullptr can exclude integer overloads, but it cannot choose the specific pointer type for you.When dealing with multiple pointer overloads, first place nullptr into a pointer variable of a clear type.

Common Errors

Error 1: Assuming nullptr can match any pointer overload

void f(int*);
void f(double*);

f(nullptr);  // ❌ 编译错误:两个指针版本都能匹配

Correct approach: first clarify the type: int* p = nullptr; f(p);

Error 2: Assigning nullptr to an integer

int n = nullptr;  // ❌ 编译错误!nullptr 不能隐式转换为整数

Correct Practice: Use 0 for integers, and use nullptr for pointers.

Error 3: Using NULL for pointer validation

if (p == NULL) { ... }  // 能工作,但不是最佳实践

Correct approach: use if (p == nullptr) or directly if (!p).

Error 4: Using nullptr as a boolean in unintended places

std::string s = nullptr;  // ❌ C++23 起直接禁止;旧标准中也是未定义行为

Correct practice: Empty strings should be represented using std::string s; or std::string s = "";.

使用建议

  • 明确目标:在开始前确定您的具体需求,以便选择最合适的工具或教程。
  • 充分利用资源:参考官方文档、教程和博客,这些资料能帮助您快速上手并解决问题。
  • 实践应用:通过动手操作项目或编写代码来巩固学习成果,提升实际操作能力。
  • 问题解决:遇到困难时,查阅参考资料或寻求社区支持,逐步培养独立解决问题的能力。
  • 分享经验:完成项目后,可以撰写文章或博客分享心得,帮助其他学习者。

如果需要针对特定领域(如单片机、机器人或环境搭建)的进一步建议,请提供更多信息,我将为您细化内容。

  1. Always use nullptr instead of NULL or 0: this is a modern C++ idiom to avoid type ambiguity.
  2. Smart pointers are also available via nullptr: such as std::shared_ptr<T> p = nullptr;.
  3. Checking for non-empty with if (ptr): Equivalent to if (ptr != nullptr), more concise.
  4. Do not assign nullptr to non-pointer types: Integers, strings, and similar types should not be initialized with nullptr.

Summary

  • nullptr is a type-safe null pointer constant, replacing NULL and 0.
  • The type of nullptr is std::nullptr_t, and it can only be implicitly converted to a pointer type.
  • In overloaded functions, nullptr correctly matches the pointer version, while NULL does not.
  • Always use nullptr in modern C++.
音乐页