Back in C ++ 03, the null pointer was defined by the ISO specification (& sect; 4.10 / 1) as
The null pointer constant is an integral constant expression (5.19) of the rvalue of an integer type that evaluates to zero.
This is why in C ++ you can write
int* ptr = 0;
In C, this rule is similar, but slightly different (& sect; 6.3.2.3/3):
An integer constant expression with a value of 0 or such an expression cast for type void * is called a null pointer constant. 55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
Therefore both
int* ptr = 0;
and
int* ptr = (void *)0
are legal. However, I assume that the void* cast is done so that expressions such as
int x = NULL;
issues a compiler warning for most systems. In C ++, this will not be legal because you cannot implicitly convert void* to another type of pointer implicitly without a cast. For example, it is illegal:
int* ptr = (void*)0;
However, this leads to problems because the code
int x = NULL;
is legal C ++. Due to this and subsequent confusion (and another case shown below), since C ++ 11, there is a nullptr keyword representing a null pointer:
int* ptr = nullptr;
It has no problems.
Another advantage of nullptr over 0 is that it works better with a system like C ++. For example, suppose I have two functions:
void DoSomething(int x); void DoSomething(char* x);
If i call
DoSomething(NULL);
It is equivalent
DoSomething(0);
which calls DoSomething(int) instead of the expected DoSomething(char*) . However, with nullptr , I could write
DoSomething(nullptr);
And it will call the DoSomething(char*) function as expected.
Similarly, suppose I have a vector<Object*> and want each element to be a null pointer. Using the std::fill algorithm, I can try to write
std::fill(v.begin(), v.end(), NULL);
However, this does not compile, because the template system treats NULL as an int , not a pointer. To fix this, I would have to write
std::fill(v.begin(), v.end(), (Object*)NULL);
This is ugly and somewhat striking the purpose of the template system. To fix this, I can use nullptr :
std::fill(v.begin(), v.end(), nullptr);
And since nullptr , as you know, has a type corresponding to a null pointer (in particular, std::nullptr_t ), this will compile correctly.
Hope this helps!