Null VS Nullptr (Why Was It Replaced)

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 type std::nullptr_t is a null pointer constant, and that an integral null pointer constant can be converted to std::nullptr_t. The opposite direction is not allowed. This allows overloading a function for both pointers and integers, and passing nullptr to select the pointer version. Passing NULL or 0 would confusingly select the int version.

  • A cast of nullptr_t to an integral type needs a reinterpret_cast, and has the same semantics as a cast of (void*)0 to an integral type (mapping implementation defined). A reinterpret_cast cannot convert nullptr_t to any pointer type. Rely on the implicit conversion if possible or use static_cast.

  • The Standard requires that sizeof(nullptr_t) be sizeof(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



Leave a reply



Submit