In C++, NULL is a macro that is typically defined as the integer value 0. It has been used traditionally to represent a null pointer. However, this can lead to ambiguity, particularly in function overloading, because NULL is not type-safe and can be treated as an integer.

On the other hand, nullptr was introduced in C++11 as a new keyword to represent a null pointer. It provides a type-safe way to represent null pointers. Unlike NULL, nullptr is of type std::nullptr_t, and it can be implicitly converted to any pointer type, making it a much safer and clearer option for representing null pointers in modern C++ code.

C++ expert Alex Allain says it perfectly here:

...imagine you have the following two function declarations:

void func(int n);
void func(char *s);

func( NULL ); // guess which function gets called?

Although it looks like the second function will be called--you are, after all, passing in what seems to be a pointer--it's really the first function that will be called! The trouble is that because NULL is 0, and 0 is an integer, the first version of func will be called instead.

This is the kind of thing that, yes, doesn't happen all the time, but when it does happen, is extremely frustrating and confusing. If you didn't know the details of what is going on, it might well look like a compiler bug. A language feature that looks like a compiler bug is, well, not something you want.

Enter nullptr. In C++11, nullptr is a new keyword that can (and should!) be used to represent NULL pointers; in other words, wherever you were writing NULL before, you should use nullptr instead. It's no more clear to you, the programmer, (everyone knows what NULL means), but it's more explicit to the compiler, which will no longer see 0s everywhere being used to have special meaning when used as a pointer.

Allain ends his article with:

Regardless of all this--the rule of thumb for C++11 is simply to start using nullptr whenever you would have otherwise used NULL in the past.