Question
In C++11, a new feature called nullptr was introduced, and I want to understand what it is and why it is preferred over NULL.
For example:
int* x = nullptr;
MyClass* obj = nullptr;
I understand that nullptr replaces the older NULL macro, but I do not fully understand how it works.
I have read that nullptr is a keyword and that it has the type std::nullptr_t, which can be implicitly converted to any pointer type or pointer-to-member type. It cannot be implicitly converted to integer types, except bool.
How can something be both a keyword and an instance of a type?
Also, besides the common examples, can you show practical cases where nullptr is better than using 0 or NULL in C++?
Short Answer
By the end of this page, you will understand what nullptr is in C++, why it was added in C++11, how std::nullptr_t relates to it, and why it is safer than NULL or 0. You will also see examples involving overload resolution, comparisons, and real-world coding patterns where nullptr avoids bugs and makes code clearer.
Concept
nullptr is the C++11 null pointer literal. It represents “this pointer points to nothing” in a type-safe way.
Before C++11, programmers often used:
0
or:
NULL
for null pointers. The problem is that 0 is fundamentally an integer literal, and NULL is usually just a macro that expands to 0 or 0L. That means they can behave like integers in contexts where you really intended a pointer.
nullptr fixes this problem.
What nullptr really is
nullptris a keyword in the language.- It is a special literal value, similar in spirit to
true,false, or numeric literals. - The type of that literal is
std::nullptr_t.
So these two statements are both true:
nullptris a language keyword.- The expression
nullptrhas the typestd::nullptr_t.
That is not unusual in C++. For example:
trueis a keyword.- The expression
truehas typebool.
Likewise:
nullptris a keyword.- The expression
nullptrhas typestd::nullptr_t.
Why this matters
Because std::nullptr_t is a dedicated type for null pointer values:
- it converts to any raw pointer type,
- it converts to any pointer-to-member type,
- it does not act like a normal integer.
This makes code safer and helps the compiler choose the correct function overloads.
Why NULL is weaker
NULL is not magical in C++. It is usually defined like one of these:
#define NULL 0
or:
#define NULL 0L
So when you write:
foo(NULL);
you may actually be passing an integer constant, not a true null pointer literal with its own type.
That can lead to:
- ambiguous overloads,
- wrong function calls,
- less readable code,
- bugs that
nullptravoids.
Key rule
Use nullptr whenever you mean a null pointer in modern C++.
Mental Model
Think of pointers as street addresses.
- A normal pointer holds the address of a real house.
- A null pointer means “no house exists here.”
Before nullptr, C++ often used the number 0 as a special code meaning “no address.” That worked, but it was awkward because 0 is also just the number zero.
So imagine writing on a form:
0could mean “house number zero” or “no address.”nullptris like having a dedicated checkbox labeled No Address.
That makes your intent obvious to both the compiler and other programmers.
Another useful analogy:
0is a general-purpose symbol.nullptris a purpose-built tool.
If you need to tighten a screw, you can sometimes force a coin to work, but a screwdriver is the right tool. nullptr is the right tool for null pointers.
Syntax and Examples
Basic syntax
int* p = nullptr;
char* text = nullptr;
This means both pointers currently point to nothing.
Checking for null
if (p == nullptr) {
std::cout << "p is null\n";
}
You will also often see:
if (!p) {
std::cout << "p is null\n";
}
That works because pointers can be used in boolean contexts.
Function call example
#include <iostream>
void print(int value) {
std::cout << "int overload: " << value << "\n";
}
void print(int* ptr) {
std::cout << "pointer overload\n";
}
int main() {
print(0); // calls print(int)
print(nullptr); // calls print(int*)
}
Why this is important
If you used NULL and it expands to 0, then:
print(NULL);
might call print(int) instead of the pointer version. That is exactly the kind of bug nullptr prevents.
Another example with templates
#include <iostream>
#include <cstddef>
void check(int*) {
std::cout << "int pointer\n";
}
void check(std::nullptr_t) {
std::cout << "nullptr itself\n";
}
int main() {
check(nullptr);
}
Here, nullptr has its own real type: std::nullptr_t. That is why you can overload on it directly.
Pointer-to-member example
struct MyClass {
int value;
};
int MyClass::* memberPtr = nullptr;
nullptr also works for pointer-to-member types, not just normal pointers.
Step by Step Execution
Consider this program:
#include <iostream>
void show(int) {
std::cout << "int version\n";
}
void show(const char*) {
std::cout << "pointer version\n";
}
int main() {
show(0);
show(nullptr);
}
Step-by-step
1. The compiler sees two overloads
void show(int)
void show(const char*)
One accepts an integer, and one accepts a pointer.
2. show(0) is called
show(0);
0is an integer literal.- The best match is
show(int).
So the output is:
int version
3. show(nullptr) is called
show(nullptr);
nullptrhas typestd::nullptr_t.- It converts naturally to pointer types.
- The best match is
show(const char*).
So the output is:
pointer version
Final output
int version
pointer version
What this demonstrates
Although 0 can be used as a null pointer constant in older C++, it is still an integer literal. nullptr is specifically designed to mean a null pointer, so overload resolution becomes clearer and safer.
Real World Use Cases
1. Initializing pointers safely
FILE* file = nullptr;
This makes it obvious that the pointer does not currently refer to a valid object.
2. Optional ownership or resources
class Logger {
std::ofstream* stream = nullptr;
};
A null pointer can mean “resource not available yet.”
3. Returning “not found” from pointer-based APIs
Node* findNode(const std::string& id) {
return nullptr;
}
This clearly signals that no object was found.
4. Linked lists and trees
struct Node {
int value;
Node* next = nullptr;
};
Many data structures use null pointers to mark the end or absence of children.
5. Interfacing with older APIs
When working with libraries that still use raw pointers, nullptr expresses null safely:
sendBuffer(nullptr, 0);
6. Callback or handler pointers
void (*handler)(int) = nullptr;
This means no callback is registered yet.
Real Codebase Usage
In real codebases, nullptr is most commonly used as part of defensive programming and clear intent.
Guard clauses
void process(User* user) {
if (user == nullptr) {
return;
}
// safe to use user
}
This quickly exits when an invalid pointer is passed.
Constructor member initialization
class Engine {
public:
Engine() : currentTask(nullptr) {}
private:
Task* currentTask;
};
This prevents uninitialized pointer bugs.
Error handling in legacy pointer APIs
Connection* connect() {
if (!serverAvailable()) {
return nullptr;
}
return new Connection();
}
Configuration or optional dependency injection
class Service {
public:
Service(Logger* logger = nullptr) : logger(logger) {}
private:
Logger* logger;
};
This means the logger is optional.
Overload clarity
Developers use nullptr to ensure the pointer overload is selected.
openResource(nullptr);
That is much clearer than:
openResource(0);
Modern style note
In modern C++, smart pointers are often preferred over raw pointers for ownership. But even then, nullptr is still used:
std::unique_ptr<Item> item = nullptr;
or:
if (item == nullptr) {
// no object owned
}
Common Mistakes
1. Using NULL in modern C++
Problem
void log(int);
void log(char*);
log(NULL);
If NULL is 0, the integer overload may be chosen.
Better
log(nullptr);
2. Assuming nullptr is the same as integer zero
Problem
int x = nullptr; // error
nullptr is not an integer.
Fix
Use it only where a pointer-like null value is intended.
int* p = nullptr;
3. Forgetting that null pointers must not be dereferenced
Problem
int* p = nullptr;
std::cout << *p; // undefined behavior
Fix
Check before dereferencing.
if (p != nullptr) {
std::cout << *p;
}
4. Mixing null checks with unrelated integer logic
Problem
if (p == 0) {
// works, but less clear
}
Better
if (p == nullptr) {
// clearly a pointer check
}
5. Thinking nullptr removes all pointer problems
nullptr only improves null pointer representation. It does not solve:
- dangling pointers,
- memory leaks,
- double deletes,
- ownership confusion.
For those, modern C++ often uses smart pointers and references.
Comparisons
| Concept | Type | Intended meaning | Safer for overloads? | Recommended in modern C++? |
|---|---|---|---|---|
0 | int literal | Numeric zero, sometimes null pointer constant | No | No |
NULL | Usually macro to 0 or 0L | Null pointer by convention | No | No |
nullptr | std::nullptr_t | Null pointer literal | Yes | Yes |
nullptr vs 0
0is an integer literal.nullptris specifically a null pointer literal.nullptravoids accidental calls to integer overloads.
nullptr vs NULL
NULLis usually a macro, not a real language feature.nullptris a keyword with its own type.nullptris clearer, safer, and more modern.
nullptr vs uninitialized pointer
int* p; // uninitialized, dangerous
int* q = nullptr; // initialized safely
An uninitialized pointer contains garbage. nullptr is a known safe state meaning “points to nothing.”
Cheat Sheet
Quick reference
Declare a null pointer
int* p = nullptr;
Check for null
if (p == nullptr) {}
if (p != nullptr) {}
if (!p) {}
Important facts
nullptrwas added in C++11.nullptris a keyword.- The type of
nullptrisstd::nullptr_t. - It converts to any pointer type.
- It converts to any pointer-to-member type.
- It does not convert to normal integer types.
- Prefer
nullptroverNULLand0.
Good uses
MyClass* obj = nullptr;
return nullptr;
functionTakingPointer(nullptr);
Avoid
MyClass* obj = 0;
MyClass* obj = NULL;
Common edge case
Overloads:
void f(int);
void f(char*);
Then:
f(0); // int overload
f(nullptr); // pointer overload
FAQ
What is the type of nullptr in C++?
The type of nullptr is std::nullptr_t.
Is nullptr a keyword or an object?
It is a keyword that denotes a special literal value. That literal has the type std::nullptr_t.
Why is nullptr better than NULL?
nullptr has its own type and behaves like a real null pointer literal. NULL is usually just a macro for 0, which can cause overload and type-safety problems.
Why is nullptr better than 0?
0 is an integer literal. nullptr is specifically for pointers, so it is clearer and safer.
Can nullptr be compared with pointers?
Yes. It can be compared with any pointer type and pointer-to-member type.
Can nullptr be assigned to an int?
No. It is not implicitly convertible to normal integer types.
Does nullptr work with smart pointers?
Yes. Smart pointers like std::unique_ptr and std::shared_ptr can be initialized or compared with nullptr.
Should I still use NULL in modern C++?
No. In modern C++, prefer nullptr whenever you mean a null pointer.
Mini Project
Description
Build a small C++ program that simulates looking up a user by ID and returning a pointer. This project demonstrates how nullptr is used to represent “not found,” how to check for null safely, and how it improves readability over 0 or NULL. It also reinforces safe pointer initialization and basic function design.
Goal
Create a program that searches for a user and prints either the user name or a clear “not found” message using nullptr safely.
Requirements
[ "Define a User struct with an id and a name.", "Create a function that returns a User pointer and returns nullptr when no match is found.", "Store a small fixed collection of users and search through it.", "Check the returned pointer before dereferencing it.", "Print a success message when a user is found and a failure message when the result is nullptr." ]
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.