The Problem with NULL
In C and C++, the NULL macro has been the traditional way to represent a null pointer. However, its definition differs between the two languages, leading to potential ambgiuities, especially in C++.
In C, NULL is typically defined as (void *) 0, a pointer to memory address zero. The C language allows implicit conversion from void* to other pointer types, making this definition versatile.
#ifndef NULL
#define NULL ((void *) 0)
#endif
C++, being a strongly-typed language, disallows such implicit conversions. To maintain backward compatibility with C, the C++ standard defines NULL as the integer constant 0. This can create problems when 0 could be interpreted as an integer or a null pointer.
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *) 0)
#endif
#endif
Introducing nullptr
To address the ambiguity of NULL, C++11 introduced the nullptr keyword. nullptr is a prvalue of type std::nullptr_t, which is a distinct type designed specifically for representing null pointers. This provides type safety and clarity.
Unlike NULL, nullptr cannot be implicitly converted to an integral type. It can only be converted to a pointer type, ensuring that it is always treated as a pointer and not an integer.
Resolving Ambiguity with Function Overloading
A common scenaroi where NULL causes issues is with function overloading. Consider the following overloaded functions:
void process_data(int value);
void process_data(char* text);
// Which function is called?
process_data(NULL);
Because NULL is defined as 0 in C++, the call process_data(NULL) will resolve to process_data(int), as the compiler interprets the integer literal 0 as matching the int parameter. This is often not the intended behavior.
Using nullptr eliminates this ambiguity:
// This will unambiguously call process_data(char*)
process_data(nullptr);
The compiler now correctly identifies nullptr as a pointer type and selects the appropriate overloaded function.
Why Use nullptr?
- Type Safety:
nullptrhas a specific type, preventing unintended conversions to integers. - Clarity: It explicitly signifies a null pointer, improving code readability.
- Avoids Ambiguity: It resolves issues in contexts like function overloading where
NULLor0can be ambiguous.
For modern C++ development, nullptr is the recommended way to represent null pointers.