C++11: nullptr

In C and C++ we use the preprocessor macro NULL to say a pointer is not pointing to anywhere right now.

The problem with NULL is that underneath it is just a plain 0.

Consider the problem looking at this code excerpt:

#include <iostream>

using namespace std;

void m(int x)
{
	cout << x << endl;
}

void m(const char* x)
{
	cout << (x == NULL ? "NULL" : x) << endl;
}

int main()
{
  m(12);
  m(NULL);
  return 0;
}

If you try to compile it using g++ 4.6, you will get something like:

test.cpp: In function 'int main()':
test.cpp:19:9: error: call of overloaded 'm(NULL)' is ambiguous
test.cpp:19:9: note: candidates are:
test.cpp:5:6: note: void m(int)
test.cpp:10:6: note: void m(const char*)

Why does the compiler consider the m(NULL) ambiguous?

Because it cannot decide if NULL is actually a pointer (because it is a 0) or an integer (because NULL is… a 0).

C++11 introduces nullptr; a keyword that unambiguously represents a pointer pointing to nowhere; no 0 at all.

Pros:

  • It is a strongly typed null pointer, like Java or C# null.
  • No ambiguity when trying to pass a null pointer to something accepting an int.
  • It is a keyword, so you cannot define it to whatever you want.

Cons:

  • If you have some symbol called nullptr used in a lot of places in your code, you will need to edit your source code to rename it.

So, if you change the main method of my example above to:

int main()
{
  m(12);
  m(nullptr);
  return 0;
}

Your code will compile and execute with no problems.

As Joe noted in his comment on this post (thanks Joe!), the type of nullptr is actually nullptr_t, so, you would be also able to overload the m() function to perform different if the argument is nullptr, as shown in this example below:

void m(int x)
{
	cout << x << endl;
}

void m(const char* x)
{
	cout << x << endl;
}

void m(nullptr_t)
{
	cout << "nullptr!" << endl;
}

int main()
{
  m(12);
  m(nullptr);
  return 0;
}
Advertisements

5 thoughts on “C++11: nullptr

  1. The type of nullptr is nullptr_t, and you can overload on it. This is most useful when you have a function f that is overloaded on two or more pointer types so that f(nullptr) is ambiguous. If you also overload f on nullptr_t, then f(nullptr) will always call f(nullptr_t).

  2. It’s been a long time, but I feel obliged to point out a minor mistake: in both 2003 and 2011 Standard versions NULL is implementation-defined, but a footnote explicitly forbids “(void*)0” definition.
    That’s not surprising, should NULL be defined as (void*)0, code like
    Foo* foo = NULL;
    would be ill-formed, since void* in C++ (in contrast to C) is not implicitly convertible to other pointer types. Same footnote mentiones “0” and “0L” as viable options.
    (Note that the example program could be well-formed if NULL was defined as 0)
    Hope it doesn’t sound negative – I consider your articles a nice introduction to C++11 features :)

      1. Cloooose, but not perfect :) If NULL was a plain zero, f(int) overload would be choosen, since it’s an exact match, while f(char*) requires pointer conversion, which is strictly worse match wrt overload resolution rules. You can easily check it by calling f(0). As of gcc 4.7.1, NULL seems to be defined as “__null”, which looks like a special internal symbol (especially since “NULL” appears unchanged in the diagnostics). Haven’t checked, but I bet it’s the same in many if not all previous releases.
        I promise to refrain from further harrasment :D

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s