10

I'm just a little bit confused.

When should I use nullptr?

I've read on some sites that it should always be used, but I can't set nullptr for a non-pointer for example:

int myVar = nullptr; // Not a pointer ofcourse

Should I always use NULL non-pointers and nullptr for pointers?

Thanks to any help! I'm very new to c++ 11 (and c++ overall).

user2774429
  • 201
  • 2
  • 7
  • 7
    You shouldn't be setting `int` variables to `NULL` either, `NULL` is only intended for pointer types. It's only with `nullptr` that it became possible to enforce this. –  Sep 12 '13 at 22:07

2 Answers2

11

Always use nullptr when initializing pointers to a null pointer value, that's what it is meant for according to draft n3485.

[lex.nullptr] paragraph 1

The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t. [ Note: std::nullptr_t is a distinct type that is neither a pointer type nor a pointer to member type; rather, a prvalue of this type is a null pointer constant and can be converted to a null pointer value or null member pointer value. [...] — end note ]

Now onto the use of NULL.

According to the same draft it shall be defined as follows.

[diff.null] paragraph 1

The macro NULL, [...] is an implementation-defined C ++ null pointer constant in this International Standard.

and null pointer constant as follows.

[conv.ptr] paragraph 1

A null pointer constant is an integral constant expression [...] prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t.

That is, it is implementation-defined behavior whether NULL is defined as an integer prvalue evaluating to zero, or a prvalue of type std::nullptr_t. If the given implementation of the standard library chooses the former, then NULL can be assigned to integer types and it's guaranteed it will be set to zero, but if the later is chosen, then the compiler is allowed to issue an error and declare the program ill-formed.

In other words, although conditionally valid [read IB], initializing an integer using NULL is most probably a bad idea, just use 0 instead.

On the other hand, according to the above NULL is guaranteed to initialize pointers to a null pointer value, much like nullptr does, but while NULL is a macro, what accompanies several caveats, nullptr is prvalue of a specific type, for which type checking and conversion rules apply. That's mostly why nullptr should be prefered.

Community
  • 1
  • 1
brunocodutra
  • 2,329
  • 17
  • 23
  • "and you have no guarantees of what value it has when converted to an integer on all platforms" You do. C++ (unlike C) requires `NULL` to be an integer constant with a value of zero, so converting `NULL` to any specific integer type has well-defined behaviour (even though it's a bad idea, since that isn't what it's meant for at all). There's no conversion from pointer to int, if that's what you were thinking. –  Sep 12 '13 at 22:13
  • @hvd there's at least one standard according to which the value of `NULL` is IB – brunocodutra Sep 12 '13 at 22:16
  • 1
    It's implementation-defined *which* null pointer constant is used, but it must be a null pointer constant, and only integer constants with a value of 0 are null pointer constants. The implementation-defined aspect allows implementations to define `NULL` as, for example, `0L`. Some implementations want to make sure `sizeof(NULL) == sizeof(void*)`, and if the C++ standard simply required `NULL` to expand to `0`, that would not be possible. –  Sep 12 '13 at 22:18
  • @hvd I stand corrected. The section pointed out by DyP does state exactly that. Thank you for pointing that out, I will delete this passage in a few. – brunocodutra Sep 12 '13 at 22:22
  • 3
    Actually, I was somewhat wrong. As of C++11, the definition of "null pointer constant" also allows expressions of type `nullptr_t`, so `#define NULL nullptr` seems to be valid now. That means `int a = NULL;`, if accepted by the compiler, must still set `a` to `0`, but this is no longer required to be accepted, the compiler may alternatively give a hard error. –  Sep 12 '13 at 22:27
  • @hvd My understanding of *evaluates to zero or a prvalue of type std::nullptr_t* is that it should evaluate to zero when converting to an integer and to `nullptr` when converting to a pointer. Am I missunderstanding anything? – brunocodutra Sep 12 '13 at 22:31
  • 2
    @brunocodutra It's the other way around, an integer constant expression that evaluates to zero is a null pointer constant, and a prvalue of type `std::nullptr_t` is also a null pointer constant. A null pointer constant is explicitly required to support conversion to pointer types, and to `bool`, but not to other types unless required for other reasons. Those other reasons do exist for `0` (it's already `int`, so it's assignable to `int`), but not for `nullptr` (so there's nothing in the standard that says it's convertible to `int`). –  Sep 12 '13 at 22:35
  • @brunocodutra You seem to be reading it as if the user of a null pointer constant can decide whether it's used as an integer constant expression that evaluates to zero, or as a prvalue of type `std::nullptr_t`, and I can see how you would read it like that, but it's the fact that an expression is integer constant zero that makes it a null pointer constant. –  Sep 12 '13 at 22:39
  • @hvd you are right, I get it now, thanks again, I'll ammend the answer. – brunocodutra Sep 12 '13 at 22:40
2

consider the two function overloads:

void foo(int)
void foo(int*)

in C++, people tend to use 0 as a null value. Other people use NULL. (NULL is really just a fancy macro for 0)

If you call foo(0) or foo(NULL), it becomes ambiguous which one should be called. foo(nullptr) clears up this ambiguity, and will always call foo(int*).

Nicolas Louis Guillemot
  • 1,570
  • 1
  • 10
  • 23
  • [support.types]/3 "The macro `NULL` is an implementation-defined C++ null pointer constant" and [conv.ptr]/1 "A *null pointer constant* is an integral constant expression prvalue of integer type that evaluates to zero or a prvalue of type `std::nullptr_t`" So, it is **not** ambiguous. – dyp Sep 12 '13 at 22:17
  • 2
    How does this answer the question? – Praetorian Sep 12 '13 at 22:17
  • 2
    To clarify: It is not ambiguous in the sense of overload resolution, but worse, it's implementation-defined which overload is chosen: If the null pointer constant is of integral type, integral promotion or conversion will select `foo(int)`. Else, it is of type `std::nullptr_t`, and `foo(int*)` will be selected. – dyp Sep 12 '13 at 22:26
  • Praetorian: this explains that you should use nullptr in the face of ambiguity. – Nicolas Louis Guillemot Sep 12 '13 at 23:38
  • @NicolasLouisGuillemot You shouldn't use it in the face of ambiguity, you should always use it for pointers to not have to even think if you're facing ambiguity. – Christian Rau Sep 13 '13 at 09:59
  • Sometimes the ambiguity is intentional. Like if you want to zero-initialize any primitive type, you would go T t = 0; and it would work for pointers and ints as intended. – Nicolas Louis Guillemot Sep 13 '13 at 17:35