NULL vs nullptr (Why was it replaced?)
nullptr
has type std::nullptr_t
. It's implicitly convertible to any pointer type. Thus, it'll match std::nullptr_t
or pointer types in overload resolution, but not other types such as int
.
0
(aka. C's NULL bridged over into C++) could cause ambiguity in overloaded function resolution, among other things:
f(int);
f(foo *);
(Thanks to Caleth pointing this out in the comments.)
Why not call nullptr NULL?
Stephan T. Lavavej (member of the C++ standard committee) explained that once in a talk (55:35):
While an implementation is allowed to #define NULL nullptr
, it would break quite some uses like
int i = NULL;
and apparently there are plenty of those. So they could not force the change.
When NULL cannot be replaced by nullptr?
In practice it should be fairly safe.
But, technically, it is possible that the meaning of your program changes, without causing any compiler errors. Consider the following program:
void foo(int) { std::cout << "int\n"; }
void foo(int*) { std::cout << "int*\n"; }
int main() {
foo(NULL); // prints 'int'
foo(nullptr); // prints 'int*'
return 0;
}
Note that when there's ambiguity between an int
and a pointer when passing NULL
, the pointer version is what's almost always desired -- which means that most real programs won't have an ambiguity like that in the first place (or will use casts like (int*)NULL
to get around it, in which case replacement by nullptr
is perfectly fine).
What exactly is nullptr?
How is it a keyword and an instance of a type?
This isn't surprising. Both true
and false
are keywords and as literals they have a type ( bool
). nullptr
is a pointer literal of type std::nullptr_t
, and it's a prvalue (you cannot take the address of it using &
).
4.10
about pointer conversion says that a prvalue of typestd::nullptr_t
is a null pointer constant, and that an integral null pointer constant can be converted tostd::nullptr_t
. The opposite direction is not allowed. This allows overloading a function for both pointers and integers, and passingnullptr
to select the pointer version. PassingNULL
or0
would confusingly select theint
version.A cast of
nullptr_t
to an integral type needs areinterpret_cast
, and has the same semantics as a cast of(void*)0
to an integral type (mapping implementation defined). Areinterpret_cast
cannot convertnullptr_t
to any pointer type. Rely on the implicit conversion if possible or usestatic_cast
.The Standard requires that
sizeof(nullptr_t)
besizeof(void*)
.
What is the difference between a null pointer constant (nullptr), a null pointer value and a null member pointer value?
What is the difference between a null pointer constant (nullptr), a null pointer value and a null member pointer value?
Null pointer constant is either nullptr (or any other prvalue of type std::nullptr_t
), or integer literal of value 0. Examples of null pointer constants:
NULL // a macro for one of the others
0
0L
nullptr
std::nullptr_t fun();
fun() // also a null pointer constant
Of these, don't use the integer literals nor NULL unless you need to support older than C++11 standard.
Null pointer value is the value of a pointer type that represents null. Examples of null pointer values:
(void*)nullptr // pointer to void
(int*)nullptr // pointer to object
using void_fun = void();
(void_fun*)nullptr // pointer to function
Null member pointer value is the value of a member pointer type that represents null. Example of null member pointer values:
(int some_class::*)nullptr // pointer to data member
using mem_void_fun_ptr = void(some_class::*)(); // unfortunately cannot alias member
// function type as far as I know,
// so we alias pointer to it instead
(mem_void_fun_ptr)nullptr // pointer to member function
Note that std::nullptr_t
is not a pointer type nor a pointer to member type.
Does both NULL and nullptr point to same address or NULL points to nowhere? (I have seen in many places that nullptr points to zero address)
It might be useful to clear up some terminology. A pointer points to an object. The value of a pointer is an address value. There is a special address value for pointers that do not point to an object. We call such pointers "null pointers". When you assign the NULL
or nullptr
values to a pointer, it becomes a null pointer.
Since all null pointers compare equal, static_cast<void*>(NULL) == static_cast<void>(nullptr)
.
Is it safe to #define NULL nullptr?
I have seen below macro in topmost header file:
You shouldn't have seen that, the standard library defines it in <cstddef>
(and <stddef.h>
). And, IIRC, according to the standard, redefining names defined by standard header files results in undefined behaviour. So from a purely standardese viewpoint, you shouldn't do that.
I've seen people do the following, for whatever reason their broken mind thought of:
struct X{
virtual void f() = NULL;
}
(As in [incorrectly]: "set the virtual table pointer to NULL
")
This is only valid if NULL
is defined as 0
, because = 0
is the valid token for pure-virtual functions (§9.2 [class.mem]
).
That said, if NULL
was correctly used as a null pointer constant, then nothing should break.
However, beware that, even if seemingly used correctly, this will change:
void f(int){}
void f(char*){}
f(0); // calls f(int)
f(nullptr); // calls f(char*)
However, if that was ever the case, it was almost certainly broken anyways.
Can I use NULL as substitution for the value of 0?
Am I allowed to use the NULL pointer as replacement for the value of 0?
No, it is not safe to do so. NULL
is a null-pointer constant, which could have type int
, but which more typically has type void *
(in C), or otherwise is not directly assignable to an int
(in C++ >= 11). Both languages allow pointers to be converted to integers, but they do not provide for such conversions to be performed implicitly (though some compilers provide that as an extension). Moreover, although it is common for converting a null pointer to an integer to yield the value 0, the standard does not guarantee that. If you want a constant with type int
and value 0 then spell it 0
.
- Am I might crossing into Undefined Behavior with this?
Yes, on any implementation where NULL
expands to a value with type void *
or any other not directly assignable to int
. The standard does not define the behavior of your assignment on such an implementation, ergo its behavior is undefined.
- is it permissible to operate with the NULL in that way?
It is poor style, and it will break on some systems and under some circumstances. Inasmuch as you appear to be using GCC, it would break in your own example if you compiled with the -Werror
option.
- Is there anything wrong about to use NULL as numerical value in arithmetical expressions?
Yes. It is not guaranteed to have a numerical value at all. If you mean 0 then write 0, which is not only well defined, but shorter and clearer.
- And how is the result in C++ to that case?
The C++ language is stricter about conversions than is C and has different rules for NULL
, but there, too, implementations may provide extensions. Again, if you mean 0 then that's what you should write.
Should you default HMENU to nullptr or 0?
Windows API came before nullptr
. The reason for the introduction of nullptr
is that the compiler sometimes gets confused between the "zero integer" and "null pointer". This is usually a problem in function overload. The programmer might also get confused between "zero integer" and "null pointer". Using nullptr
is recommended, otherwise nullptr
, NULL
, and 0
are the same thing.
To make things more confusing, some Windows's null handles are non-zero values. For example the return value for CreateFile
is INVALID_FILE_HANDLE
when function fails. In this case you must write if(hfile != INVALID_FILE_HANDLE){success...}
The argument being made, is that if you have a habit of writing if(handle)
, instead of if(handle != specific_null_handle)
, you end up writing the wrong code when specific_null_handle
is not zero. Otherwise if(handle)
is the same code as if(handle != nullptr)
as far as the compiler is concerned.
To be consistent with Windows API, you should write NULL
, or swap NULL
with nullptr
.
Related Topics
How Does Virtual Inheritance Solve the "Diamond" (Multiple Inheritance) Ambiguity
What Are the Complexity Guarantees of the Standard Containers
How to Convert Wstring into String
Is It Good Practice to Null a Pointer After Deleting It
C++: Life Span of Temporary Arguments
Compilers and Argument Order of Evaluation in C++
How to "Return an Object" in C++
Legality of Cow Std::String Implementation in C++11
Does C++11 Allow Vector≪Const T≫
Pure Virtual Function With Implementation
How to Detect Reliably MAC Os X, Ios, Linux, Windows in C Preprocessor
Constructor Initialization-List Evaluation Order
Combining C++ and C - How Does #Ifdef _Cplusplus Work
Static Linking VS Dynamic Linking
How to Pass a Unique_Ptr Argument to a Constructor or a Function