C++ nullptr vs NULL | Type-Safe Null Pointers
이 글의 핵심
`nullptr` is a pointer literal of type `std::nullptr_t`. `NULL` and `0` are integral—use `nullptr` for clarity and correct overload and template behavior.
Introduction
nullptr (C++11) is a type-safe null pointer literal. Unlike NULL or 0, it has type std::nullptr_t and participates correctly in overload resolution and template deduction.
1. Basics
#include <iostream>
int main() {
int* ptr1 = NULL; // implementation-defined (often 0)
int* ptr2 = 0; // integer literal
int* ptr3 = nullptr; // std::nullptr_t -> pointer
std::cout << ptr1 << "\n";
std::cout << ptr2 << "\n";
std::cout << ptr3 << "\n";
return 0;
}
std::nullptr_t overloads
#include <cstddef>
void func(std::nullptr_t) {
std::cout << "nullptr_t\n";
}
void func(int) {
std::cout << "int\n";
}
int main() {
func(nullptr); // nullptr_t
// func(NULL); // ambiguous or wrong: usually calls int
func(0); // int
return 0;
}
2. Problems with NULL
Overload resolution
void process(int value) {
std::cout << "int: " << value << "\n";
}
void process(int* ptr) {
std::cout << "pointer\n";
}
int main() {
process(0); // int
process(NULL); // often int—not pointer!
process(nullptr); // pointer overload
return 0;
}
NULL is typically 0 or 0L—an integer, not a pointer type.
Template deduction
template<typename T>
void func(T value) {
std::cout << typeid(T).name() << "\n";
}
int main() {
func(0); // T = int
func(NULL); // T = int or long
func(nullptr); // T = std::nullptr_t
return 0;
}
auto deduction
auto p1 = NULL; // integral
auto p2 = nullptr; // std::nullptr_t
int* q = p2; // OK
3. Using nullptr
Initialization
int* p1 = nullptr;
std::unique_ptr<int> u = nullptr;
std::shared_ptr<int> s = nullptr;
void (*fp)() = nullptr;
Checks
if (ptr == nullptr) { }
if (!ptr) { }
if (ptr) { }
Return values
int* find(int) {
return nullptr; // clear “no result”
}
4. Examples
Linked list
struct Node {
int data;
Node* next;
Node(int d) : data(d), next(nullptr) {}
};
Repository returning “not found”
User* findById(int id) {
if (id == 1) return &someUser;
return nullptr;
}
5. Comparison table
nullptr | NULL | 0 | |
|---|---|---|---|
| Type | std::nullptr_t | integral | int |
| Overloads | pointer | int | int |
Template T | nullptr_t | int | int |
| Recommended | Yes | Legacy | Legacy |
6. Migration
Before
int* ptr = NULL;
if (ptr == NULL) { }
void f(Widget* w = NULL);
After
int* ptr = nullptr;
if (ptr == nullptr) { }
void f(Widget* w = nullptr);
clang-tidy
clang-tidy -checks='-*,modernize-use-nullptr' -fix program.cpp
Summary
nullptr: C++11 pointer literalNULL: legacy macro, integral- Overloads:
nullptrselects pointer overloads - Templates: clear deduction
- Performance: no runtime difference
Principles: Prefer nullptr in C++11+; compare with == nullptr or !ptr.
Related: C++ nullptr, Smart pointers.
Related posts
- C++ nullptr
- C++ async & launch
Keywords
C++, nullptr, NULL, null pointer, C++11, std::nullptr_t.
More links
- C++ Atomic operations
- C++ auto keyword