Take the 2-minute tour ×

This piece of code conceptually does the same thing for the three pointers (safe pointer initialization):

int* p1 = nullptr;
int* p2 = NULL;
int* p3 = 0;

And so, what are the advantages of assigning pointers nullptr over assigning them the values NULL or 0?

share|improve this question
For one thing, an overloaded function taking int and void * won't choose the int version over the void * version when using nullptr. –  chris Dec 11 '12 at 8:36
Well f(nullptr) is different from f(NULL). But as far as the above code is concerned(assigning to a local variable), all the three pointers are exactly the same. The only advantage is code readability. –  balki Dec 11 '12 at 18:00
I am in favor of making this an FAQ, @Prasoon. Thanks! –  sbi Dec 12 '12 at 11:01

6 Answers 6

up vote 66 down vote accepted

In that code, there doesn't seem to be an advantage. But see these overloaded functions:

void f(char const *ptr);
void f(int v);

f(NULL);  //which function will be called?

Which function will be called? Of course, the intention here is to call f(char const *), but in reality f(int) will be called!! That is a big problem1, isn't it?

So, the solution to such problems is to use nullptr:

f(nullptr); //first function is called

Of course, that is not the only advantage of nullptr. Here is another:

template<typename T, T *ptr>
struct something{};                     //primary template

struct something<nullptr_t, nullptr>{};  //partial specialization for nullptr

Since in template, the type of nullptr is deduced as nullptr_t, so you can write this:

template<typename T>
void f(T *ptr);   //function to handle non-nullptr argument

void f(nullptr_t); //an overload to handle nullptr argument!!!

1. In C++, NULL is defined as #define NULL 0, so it is basically int, that is why f(int) is called.

share|improve this answer
Don't see that kind of overload in practice very often, but yeah.... –  Mehrdad Dec 11 '12 at 8:44
As what Mehrdad had stated, these kinds of overloads are pretty rare. Are there other relevant advantages of nullptr? (No. I'm not demanding) –  Mark Garcia Dec 11 '12 at 8:46
@MarkGarcia, This might be helpful: stackoverflow.com/questions/13665349/… –  chris Dec 11 '12 at 9:09
Your footnote seems backwards. NULL is required by the standard to have an integral type, and that's why it's typically defined as 0 or 0L. Also I'm not sure I like that nullptr_t overload, since it catches only calls with nullptr, not with a null pointer of a different type, like (void*)0. But I can believe it has some uses, even if all it does is save you defining a single-valued place-holder type of your own to mean "none". –  Steve Jessop Dec 11 '12 at 9:43
Another advantage (though admittedly minor) may be that nullptr has a well-defined numeric value whereas null pointer constants do not. A null pointer constant is converted to the null pointer of that type (whatever that is). It is required that two null pointers of the same type compare identically, and boolean conversion turns a null pointer into false. Nothing else is required. Therefore, it is possible for a compiler (silly, but possible) to use e.g. 0xabcdef1234 or some other number for the null pointer. On the other hand, nullptr is required to convert to numeric zero. –  Damon Dec 11 '12 at 12:34

The real motivation here is perfect forwarding.


void f(int* p);
template<typename T> void forward(T&& t) {
int main() {
    forward(0); // FAIL

Simply put, 0 is a special value, but values cannot propagate through the system- only types can. Forwarding functions are essential, and 0 can't deal with them. Thus, it was absolutely necessary to introduce nullptr, where the type is what is special, and the type can indeed propagate. In fact, the MSVC team had to introduce nullptr ahead of schedule after they implemented rvalue references and then discovered this pitfall for themselves.

There are a few other corner cases where nullptr can make life easier- but it's not a core case, as a cast can solve these problems. Consider

void f(int);
void f(int*);
int main() { f(0); f(nullptr); }

Calls two separate overloads. In addition, consider

void f(int*);
void f(long*);
int main() { f(0); }

This is ambiguous. But, with nullptr, you can provide

void f(std::nullptr_t)
int main() { f(nullptr); }
share|improve this answer
Funny. The half of the answer is same as other two answers which according to you is "quite incorrect" answers!!! –  Nawaz Dec 12 '12 at 4:53

C++11 introduces nullptr, it is known as the Null pointer constant and It improves type safety and resolves ambiguous situations unlike the existing implementation dependent null pointer constant NULL. To be able to understand the advantages of nullptr. we first need to understand what is NULL and what are the problems associated with it.

What is NULL exactly?

Pre C++11 NULL was used to represent a pointer that has no value or pointer that does not point to anything valid. Contrary to the popular notion NULL is not a keyword in C++. It is an identifier defined in standard library headers. In short you cannot use NULL without including some standard library headers. Consider the Sample program:

int main()
    int *ptr = NULL;
    return 0;


prog.cpp: In function 'int main()':
prog.cpp:3:16: error: 'NULL' was not declared in this scope

The C++ standard defines NULL as an implementation defined macro defined in certain standard library header files. The origin of NULL is from C and C++ inherited it from C. The C standard defined NULL as 0 or (void *)0. But in C++ there is a subtle difference.
C++ could not accept this specification as it is. Unlike C, C++ is a strongly typed language.(C does not require explicit cast while from void* to any type while C++ mandates a explicit cast) .This makes the definition of NULL specified by C standard useless in many C++ expressions, for example:

std::string * str = NULL;         //Case 1
void (A::*ptrFunc) () = &A::doSomething;
if (ptrFunc == NULL) {}           //Case 2

If NULL was defined as (void *)0. Both of above expressions would not work.

  • Case 1: Will not compile because a automatic cast is needed from void * to std::string.
  • Case 2: Will not compile because cast from void * to pointer to member function is needed.

So unlike C, C++ Standard mandated to define NULL as numeric literal 0 or 0L.

So what is the need for another null pointer constant when we have NULL already?

Though C++ Standards committee came up with a NULL definition which will work for C++, this definition had its own fair share of problems. NULL worked well enough for almost all scenarios but not all. It gave surprising and erroneous results for certain rare scenarios. For example:

void doSomething(int)
    std::cout<<"In Int version";
void doSomething(char *)
   std::cout<<"In char* version";

int main()
    return 0;


In Int version

Clearly, the intention seems to be to call the version which takes char* as the argument, but as the output shows the function which takes an int version gets called. This is because NULL is an numeric literal.

Furthermore, Since it is implementation defined whether NULL can be 0 or 0L there can lot of confusion in function overload resolution.

Sample Program:

#include <cstddef>

void doSomething(int);
void doSomething(char *);

int main()
  doSomething(static_cast <char *>(0));    // Case 1
  doSomething(0);                          // Case 2
  doSomething(NULL)                        // Case 3

Analyzing the above snippet:

  • Case 1: calls doSomething(char *) as expected
  • Case 2: calls doSomething(int) but maybe char* version was be desired because 0 IS also a null pointer.
  • Case 3: If NULL is defined as 0,
    calls doSomething(int) when perhaps doSomething(char *) was intended, perhaps resulting in logic error at runtime.
    While, if NULL is defined as 0L,
    Call is ambiguous and results in compilation error.

So depending on implementation the same code can give various outcomes, which is clearly undesired. Naturally, the C++ standards committee wanted to correct this and that is the prime motivation for nullptr.

So what is nullptr and how it avoids problems of NULL?

C++11 introduces a new keyword nullptr to serve as null pointer constant. Unlike NULL its behavior is not implementation defined. It is not an Macro but it has its own type. nullptr has the type std::nullptr_t. C++11 appropriately defines properties for the nullptr to avoid the disadvantages of NULL. To summarize its properties:

Property 1: It has it’s own type std::nullptr_t and
Property 2: It is implicitly convertible and comparable to any pointer type or pointer-to-member type but
Property 3: It is not implicitly convertible or comparable to integral types, except for bool.

Consider the following example:

void doSomething(int)
    std::cout<<"In Int version";
void doSomething(char *)

int main()
    char *pc = nullptr;      // Case 1
    int i = nullptr;         // Case 2
    bool flag = nullptr;     // Case 3

    doSomething(nullptr);    // Case 4
    return 0;

In the above program,

  • Case 1: OK - Property 2
  • Case 2: Not Ok - Property 3
  • Case 3: OK - Property 3
  • Case 4: No confusion - Calls char * version, Property 2 & 3

Thus introduction of nullptr avoids all the problems of good old NULL.

How and where should you use nullptr?

The rule of thumb for C++11 is simply start using nullptr whenever you would have otherwise used NULL in the past.

Standard References:

C++11 Standard: C.3.2.4 Macro NULL
C++11 Standard: 18.2 Types
C++11 Standard: 4.10 Pointer conversions
C99 Standard: Pointers

share|improve this answer
I'm already practicing your last advice since I've known nullptr, though I did not know what difference it really does to my code. Thanks for the great answer and especially for the effort. Brought me a great deal light on the topic. –  Mark Garcia Jan 4 '13 at 7:15

Just as others have already said, its primary advantage lies in overloads. And while explicit int vs. pointer overloads can be rare, consider standard library functions like std::fill (which has bitten me more than once in C++03):

MyClass *arr[4];
std::fill_n(arr, 4, NULL);

Doesn't compile: Cannot convert int to MyClass*.

share|improve this answer

There is no direct advantage of having nullptr in the way you have shown the examples.
But consider a situation where you have 2 functions with same name; 1 takes int and another an int*

void foo(int);
void foo(int*);

If you want to call foo(int*) by passing a NULL, then the way is:

foo((int*)0); // note: foo(NULL) means foo(0)

nullptr makes it more easy and intuitive:


Additional link from Bjarne's webpage.
Irrelevant but on C++11 side note:

auto p = 0; // makes auto as int
auto p = nullptr; // makes auto as decltype(nullptr)
share|improve this answer
For reference, decltype(nullptr) is std::nullptr_t. –  chris Dec 11 '12 at 8:47
@MarkGarcia, It's a full-blown type as far as I know. –  chris Dec 11 '12 at 8:49
@MarkGarcia, It's an interesting question. cppreference has: typedef decltype(nullptr) nullptr_t;. I guess I can look in the standard. Ah, found it: Note: std::nullptr_t is a distinct type that is neither a pointer type nor a pointer to member type; rather, a prvalue of this type is a null pointer constant and can be converted to a null pointer value or null member pointer value. –  chris Dec 11 '12 at 8:50
@DeadMG: There were more than one motivations. Many other useful things can be discovered by the programmers themselves in the coming years. So you cannot say that there is only one true usage of nullptr. –  Nawaz Dec 11 '12 at 14:34
@DeadMG: But you said this answer is "quite incorrect" simply because it doesn't talk about "the true motivation" you talked about in your answer. Not only that this answer (and mine as well) received a downvote from you. –  Nawaz Dec 11 '12 at 16:54

IMO more important than those overload issues: in deeply nested template constructs, it's hard not to lose track of the types, and giving explicit signatures is quite an endeavour. So for everything that you use, the more precisely focused to the intended purpose, the better, it will reduce the need for explicit signatures and allows the compiler to produce more insightful error messages when something goes wrong.

share|improve this answer

Your Answer


