nullptr
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:
NULLis actually0(defined as#define NULL 0in C++) and is treated as an integer, leading to a type mismatch.- In some overloaded functions,
NULLmay 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
| Usage | Explanation |
|---|---|
int* p = nullptr; | initialize null pointer |
p == nullptr | Check 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 Style | Don't mix |
|---|---|---|
| null pointer | T* p = nullptr; | Understood. I will keep the placeholders NULL and 0 exactly as they are in the translation. |
| empty smart pointer | std::shared_ptr<T> p = nullptr; | Avoid manually using new/delete. |
| empty string | std::string s; or "" | Do not use nullptr. |
| may not return a value | std::optional<T> | Don't force a 'special value' into it. |
| Container is empty | v.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.
| Example | Discusses what | Newly emerged syntax | Why write it this way | Precautions |
|---|---|---|---|---|
| Example 1 | Basic usage of nullptr | nullptr、p == nullptr | Initialize the pointer to "NULL", type-safe | The type of nullptr is std::nullptr_t |
| Example 2 | Resolve overload ambiguity | How nullptr matches the pointer version in overloaded functions | NULL cannot distinguish between integer and pointer overloading, but nullptr can. | This is why nullptr is used instead of NULL. |
| Example 3 | Templates and Smart Pointers | shared_ptr = nullptr、if(sp) | Smart pointers can also be initialized with nullptr. | The bool conversion of smart pointers is equivalent to != nullptr |
| Example 4 | Multiple pointer overloading | int*、double*、nullptr | nullptr 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 = "";.
使用建议
- 明确目标:在开始前确定您的具体需求,以便选择最合适的工具或教程。
- 充分利用资源:参考官方文档、教程和博客,这些资料能帮助您快速上手并解决问题。
- 实践应用:通过动手操作项目或编写代码来巩固学习成果,提升实际操作能力。
- 问题解决:遇到困难时,查阅参考资料或寻求社区支持,逐步培养独立解决问题的能力。
- 分享经验:完成项目后,可以撰写文章或博客分享心得,帮助其他学习者。
如果需要针对特定领域(如单片机、机器人或环境搭建)的进一步建议,请提供更多信息,我将为您细化内容。
- Always use
nullptrinstead ofNULLor0: this is a modern C++ idiom to avoid type ambiguity. - Smart pointers are also available via
nullptr: such asstd::shared_ptr<T> p = nullptr;. - Checking for non-empty with
if (ptr): Equivalent toif (ptr != nullptr), more concise. - Do not assign
nullptrto non-pointer types: Integers, strings, and similar types should not be initialized withnullptr.
Summary
nullptris a type-safe null pointer constant, replacingNULLand0.- The type of
nullptrisstd::nullptr_t, and it can only be implicitly converted to a pointer type. - In overloaded functions,
nullptrcorrectly matches the pointer version, whileNULLdoes not. - Always use
nullptrin modern C++.