C++ 11 Feature: nullptr

Introduction

When working with a null pointer in C++ you can run into unexpected behavior with regards to overload resolution.

Assume you have the following code:

When running that code, the developer would most likely be surprised that no new car is added.
The explanation for this behavior lies in NULL not really being a pointer but rather a macro which is usually just declared as 0 [1].

With that knowledge it’s obvious what the code did above. Instead of calling the buildCar() function taking the engine as a parameter, it called the version for specifying the number of cars to built and passed in 0. That results in no call to addNewCar() being made.

The nullptr idiom

The C++ 98/03 standard unfortunately doesn’t provide any means to prevent this from happening which in real world applications can cause quite a bunch of bugs/unintended behavior.

While things are quite clear in the example given above, it can easily become less apparent the more complex the code grows and the effect of NULL not being a pointer can therefore be quite easily overlooked when refactoring/simplifying code.

To resolve the problem, the nullptr idiom was developed [2] which is also described in Scott Meyers’ 2nd edition of “Effective C++” (Item 25).

The solution introduces a new class called nullptr_t which is then used instead of using NULL in code.

Making use of operator overloading, instances of the class can be assigned to any pointer type but are not valid to be used with integer/floating point types and also won’t be valid for conversions specified for number values.

If we adjust our previous example to use the nullptr idiom, the code would behave as expected and adds a single car with the standard engine:

This example however also quite well depicts the limitation of that approach:
You need to include another header in the project and not being part of the C++ standard, it’s not portable when it comes to library development.

There are also other related limitations of this approach which are less likely to be applicable for most developers and hence out of scope for this blog post. [3]

nullptr in C++11

The standard committee recognized the limitation with nullptr and in the C++11-standard, introduces nullptr as a distinct keyword which can be assigned to pointers and (hence) used as an rvalue but cannot be assigned to (or converted to) non-pointer types.

The one important thing to realize is that you need to use the nullptr-keyword directly instead of keeping using NULL.

For backwards compatibility NULL is allowed to remain declared as 0 and as a developer the only way to make sure that nullptr is being used is to use the keyword directly.

Compiler support

Any recent compiler supports the feature already since years. The following shows the support in a selection of widely used compilers: [4]

  • Clang: >= 2.9 (released April 2011) [6]
  • GCC: >=4.6.0 (released March 2011) [7]
  • Intel C++: >= 12.1 (i.e. 12 Update 6 – released August 2011) [8]
  • Microsoft Visual Studio: 2010 (April 2010) [9/10]

References/Footnotes

[1] As of C++11 the macro is also allowed to be defined as a prvalue of type std::nullptr_t [5],  though to the knowledge of the author, most compilers still stick with the declaration to 0 to ensure backwards compatibility.
Also while it’s valid by the C-standard to define NULL as (void*)0 which would have also prevented the overload ambiguity, this was never valid by the C++-standard as converting type void* to another pointer type was not permitted. [11]
[2] https://en.wikibooks.org/wiki/More_C++_Idioms/nullptr
[3] “A name for the null pointer: nullptr (revision 4) – SC22/WG21/N2431 (2007-10-02)
[4] https://en.cppreference.com/w/cpp/compiler_support
[5] https://en.cppreference.com/w/cpp/types/NULL
[6] http://releases.llvm.org/
[7] https://gcc.gnu.org/releases.html
[8] https://software.intel.com/sites/default/files/44/c4/Release_NotesC_cwin_update6.pdf
[9] https://en.wikipedia.org/wiki/Microsoft_Visual_Studio
[10] https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd465215%28v%3dvs.100%29
[11] https://devblogs.microsoft.com/oldnewthing/20180307-00/?p=98175