Null pointers

A null pointer has a reserved value that is called a null pointer constant for indicating that the pointer does not point to any valid object or function. You can use null pointers in the following cases:
  • Initialize pointers.
  • Represent conditions such as the end of a list of unknown length.
  • Indicate errors in returning a pointer from a function.

A null pointer constant is an integer constant expression that evaluates to zero. For example, a null pointer constant can be 0, 0L, or such an expression that can be cast to type (void *)0. C++11 beginsC++11 defines a new null pointer constant nullptr that can only be converted to any pointer type, pointer-to-member type, or bool type.C++11 ends

You can specify any of the following values for a null pointer constant:
  • 0
  • NULL
  • C++11 begins nullptr C++11 ends
Note: NULL is a macro. It must be defined before use.

Null pointer constants

0
You can use an integer constant expression with the value 0 or an expression that is cast to(void *)0 as a null pointer constant.
NULL
The macro NULL and value 0 are equivalent as null pointer constants, but NULL is cleaner because it represents the purpose of using the constant for a pointer.
C++11 begins
nullptr
nullptr is an explicit null pointer constant. In C++, initializing null pointers with 0 or NULL have the following problems:
  • It is impossible to distinguish between a null pointer and integer 0 for overloaded functions. For example, given two overloaded functions f(int) and f(char*), the call f(0) resolves to f(int) because 0 is converted to the integral type instead of the pointer type. See Example 1.
  • A null pointer constant does not have a type-safe name. The macro NULL cannot be distinguished from the 0 constant for overloaded functions and error detection.
To solve the problems of null pointer constants, C++11 introduced a new keyword nullptr. The nullptr constant can be distinguished from integer 0 for overloaded functions. See Example 2.
A null pointer constant with the nullptr value has the following characteristics:
  • It can be converted to any pointer or pointer-to-member type.
  • It cannot be implicitly converted to any other type, except for the bool type.
  • It cannot be used in an arithmetic expression.
  • It can be compared with the integer 0.
  • It can be used in relational expressions to compare with pointers or data of the std::nullptr_t type.

See Example 3 for information about how to use nullptr as an initializer for all pointer types and in comparison expressions.

Note: It is still acceptable to assign the value 0 or NULL to a pointer.
The nullptr keyword designates a constant rvalue of type decltype(nullptr). The typedef expression is typedef decltype(nullptr) nullptr_t, of which nullptr_t is a typedef for decltype(nullptr) that is defined in <cstddef>. A non-type template parameter and argument can have the std::nullptr_t type. If a non-type template parameter is of type std::nullptr_t, the corresponding argument must be of type std::nullptr_t. See Example 4. If a non-type template parameter is of one of the following types, the type of the corresponding non-type template argument can be std::nullptr_t. The null pointer conversion occurs for the last three types:
  • std::nullptr_t
  • pointer
  • pointer-to-member
  • bool
When you use nullptr in exception handling, pay attention to the throw and catch arguments. A handler is a match for an exception object of type E if the handler is of type cv T or const T&. T is a pointer or pointer-to-member type and E is of type std::nullptr_t. See Example 5.

Examples

Example 1

This example illustrates inappropriate use of the NULL constant for overloaded functions:
#include <stdio.h>

void func(int* i){
   printf("func(int*)\n");
}

void func(int i){
   printf("func(int)\n");
}

int main(){
   func(NULL);
} 
Suppose you want the main function to call func(int* i). As a result, the main function calls func(int i) instead of func(int* i) because the constant NULL is equal to the integer 0. Constant 0 is implicitly converted to (void*)0, only when func(int i) does not exist.

Example 2

This example illustrates how nullptr is used in overloading functions:
void f( char* );
void f( int );
f( nullptr );     // calls f( char* )
f( 0 );           // calls f( int )

Example 3

The following expressions illustrate the correct and incorrect use of the nullptr constant:
char* p = nullptr;     // p has the null pointer value 
char* p1 = 0;          // p has the null pointer value 
int a = nullptr;       // error 
int a2 = 0;            // a2 is zero of integral type
if( p == 0 );          // evaluates to true 
if( p == nullptr );    // evaluates to true 
if( p );               // evaluates to false
if( a2 == 0 );         // evaluates to true 
if( a2 == nullptr );   // error, no conversion
if( nullptr );         // OK, conversion to the bool type 
if( nullptr == 0 );    // OK, comparison with 0
nullptr = 0;           // error, nullptr is not an lvalue 
nullptr + 2;           // error

Example 4

This example illustrates that a non-type template parameter or argument can have the std::nullptr_t type:
typedef decltype(nullptr) nullptr_t;
template <nullptr_t> void fun1(); // non-type template parameter

fun1<nullptr>();      // non-type template arguments 
fun1<0>();            // error. The corresponding argument must be of type
                      // std::nullptr_t if the parameter is of type std::nullptr_t.

template <int* p> void fun2(); 
fun2<nullptr>();      //Correct

template<typename T> void h( T t );
h( 0 );                   // deduces T = int
h( nullptr );             // deduces T = nullptr_t
h( (float*) nullptr );    // deduces T = float*

Example 5

This example illustrates how to use nullptr in exception handling:
int main() {
try {
   throw nullptr;
} catch(int* p) {  // match the pointer.
   return p == 0;
}
}
C++11 ends