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 defines a new null pointer constant nullptr that can only be converted to any pointer type, pointer-to-member type, or bool type.
You can specify any of the following values for a null pointer constant:
- 0
- NULL
- nullptr
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.
Beginning of C++11 only.
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) andf(char*), the call f(0) resolves to f(int) because 0 is converted to the integral type instead of the pointer type. See Example1.
- 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;
}
}
End of C++11 only.