Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

nullptr vs. NULL

117 views
Skip to first unread message

Doug Mika

unread,
May 22, 2015, 4:18:20 PM5/22/15
to
Hi to all,

When should I use NULL and when should I use nullptr? I've tried to find this on the net but I haven't been able to find anything definitive. The only thing I did find is that using nullptr anulls ambiguity when calling an overloaded function such as:

foo(int x);
foo(int* x);


with a call:
foo(NULL); //but when would we ever use this?

Mr Flibble

unread,
May 22, 2015, 4:26:07 PM5/22/15
to
For all new C++11 code never use NULL, always use nullptr.

/Flibble


Victor Bazarov

unread,
May 22, 2015, 4:32:14 PM5/22/15
to
There is no ambiguity in that, only confusion. foo(NULL) will call the
one with the 'int' argument, not the pointer.

My recommendation is "always use 'nullptr' when you mean a pointer" and
use 'NULL' only if using 'nullptr' is not an option (I haven't yet found
any occasion where that would be so, though). Generally speaking, I
think 'NULL' macro should be retired.

V
--
I do not respond to top-posted replies, please don't ask

Luca Risolia

unread,
May 22, 2015, 4:54:41 PM5/22/15
to
Il 22/05/2015 22:32, Victor Bazarov ha scritto:
> On 5/22/2015 4:18 PM, Doug Mika wrote:
>> foo(int x);
>> foo(int* x);

>> foo(NULL); //but when would we ever use this?

> There is no ambiguity in that, only confusion. foo(NULL) will call the
> one with the 'int' argument, not the pointer.

I don't think so. The above code does not compile on my C++
implementation because the overload is really ambiguous.

Victor Bazarov

unread,
May 22, 2015, 5:22:37 PM5/22/15
to
Well, I see that g++ v4.8.3 (online) claims it ambiguous, but I can't
find any place in the Standard to support that claim. Please quote the
Standard if you know what makes the following code ill-formed:

#include <iostream>
void foo(int i) { std::cout << "foo(" << i << ")\n"; }
void foo(int* pi) { std::cout << "foo ( pointer )\n"; }

int main()
{
foo(NULL);
}

In my book the only possible definition of NULL macro (0) should make a
call 'foo(NULL)' essentially 'foo(0)', which definitely does not make it
ambiguous since '0' is an int first and only convertible to a pointer
second. IOW, a null pointer constant (0) requires a standard conversion
to become a pointer, which puts it *lower* AFA the overload resolution
rank is concerned.

I think those GNU folks want to be clever, and often overdo it.

Öö Tiib

unread,
May 22, 2015, 7:41:41 PM5/22/15
to
AFAIK NULL was interger that evaluates to zero until C++11. Since C++11
it is interger zero or std::nullptr_t.

> I think those GNU folks want to be clever, and often overdo it.

They likely picked std::nullptr_t.

Richard

unread,
May 23, 2015, 11:24:05 PM5/23/15
to
[Please do not mail me a copy of your followup]

Doug Mika <doug...@gmail.com> spake the secret code
<204c9618-835a-42ba...@googlegroups.com> thusly:

>When should I use NULL and when should I use nullptr?

If all implementations you care about support nullptr, always
use nullptr and never use NULL.

You may be hampered by older implementations.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Victor Bazarov

unread,
May 26, 2015, 7:48:09 AM5/26/15
to
Either way, if it's 'nullptr_t', it should pick foo(int*), if it's
'int', it should pick 'foo(int)', in both cases the other one requires a
conversion of lower rank, if my reading is correct. If that is so, then
it still should not be ambiguous.

Now, the bad thing about picking 'nullptr_t' instead of 'int' would be
that the code that used to lead to calling 'foo(int)' could now be
calling 'foo(int*)' *silently*.

Unless I am mistaken in reading the relevant chapter 4 and chapter 13
parts... In that case, please enlighten me.

Luca Risolia

unread,
May 26, 2015, 11:26:41 AM5/26/15
to
On 26/05/2015 13:47, Victor Bazarov wrote:
> Either way, if it's 'nullptr_t', it should pick foo(int*)

std::nullptr_t is defined as decltype(nullptr). If NULL is of type
std::nullptr_t, then the first choice for foo(NULL) should be
foo(std::nullptr_t), while both foo(int*) and foo(int) should be a
second choice.

Victor Bazarov

unread,
May 26, 2015, 11:56:38 AM5/26/15
to
What if there is no foo(std::nullptr_t)? Does conversion from nullptr_t
to int* has the same rank as conversion from nullptr_t to int?

Luca Risolia

unread,
May 26, 2015, 1:41:25 PM5/26/15
to
Il 26/05/2015 17:56, Victor Bazarov ha scritto:
> On 5/26/2015 11:26 AM, Luca Risolia wrote:
>> On 26/05/2015 13:47, Victor Bazarov wrote:
>>> Either way, if it's 'nullptr_t', it should pick foo(int*)
>>
>> std::nullptr_t is defined as decltype(nullptr). If NULL is of type
>> std::nullptr_t, then the first choice for foo(NULL) should be
>> foo(std::nullptr_t), while both foo(int*) and foo(int) should be a
>> second choice.
>
> What if there is no foo(std::nullptr_t)? Does conversion from nullptr_t
> to int* has the same rank as conversion from nullptr_t to int?

std::nullptr_t cannot be converted to int, but can be implicitly
converted to int* (and to any raw pointer types). So I was imprecise in
the second part of my statement: foo(int) is not an option at all if
NULL is of type std::nullptr_t. To answer your question then, if there's
no foo(std::nullptr_t), then the only valid option would be foo(int*).
Ergo in some C++11 implementations (like mine), which complain about
ambiguities in the foo(NULL) call, NULL is not of type std::nullptr_t.

Victor Bazarov

unread,
May 26, 2015, 3:50:19 PM5/26/15
to
If we go back to the earlier post of yours:
On 5/22/2015 4:54 PM, Luca Risolia wrote:
> [..] The above code does not compile on my C++
> implementation because the overload is really ambiguous.

Doesn't what you've just written mean that the your C++ implementation
is defective? I see no other explanation why it would deem the call
'foo(NULL)' ambiguous.

Luca Risolia

unread,
May 26, 2015, 4:45:12 PM5/26/15
to
Il 26/05/2015 21:50, Victor Bazarov ha scritto:
> If we go back to the earlier post of yours:
> On 5/22/2015 4:54 PM, Luca Risolia wrote:
> > [..] The above code does not compile on my C++
> > implementation because the overload is really ambiguous.
>
> Doesn't what you've just written mean that the your C++ implementation
> is defective?

No (see below).

> I see no other explanation why it would deem the call
> 'foo(NULL)' ambiguous.

One conforming C++11 implementation is allowed define NULL as:

#define NULL 0L

in which case foo(NULL) is ambiguous if you only have the foo(int) and
foo(int*) overloads defined, because conversion from long to int and 0L
to int* are considered equally good.

Victor Bazarov

unread,
May 26, 2015, 4:56:12 PM5/26/15
to
On 5/26/2015 4:45 PM, Luca Risolia wrote:
>[..]
> One conforming C++11 implementation is allowed define NULL as:
>
> #define NULL 0L
>
> in which case foo(NULL) is ambiguous if you only have the foo(int) and
> foo(int*) overloads defined, because conversion from long to int and 0L
> to int* are considered equally good.

Aha... Thanks! Good to know. I keep forgetting about 0L.

Lőrinczy Zsigmond

unread,
May 27, 2015, 2:26:53 AM5/27/15
to
This is a long history.
Originally, NULL should represent the null-pointer (or pointer-null),
like it does in C, but someone (I won't say the name,
because I respect Bjarne Stroustrup) thought it would be very funny
to define it as integer-null.
It was illogical, but it became standard, so it cannot be changed.
After some decades there came another idea:
nullptr, which is a pointer-null.
Also it has a separate type (nullptr_t), which opens another funny
options for overloading.

For example, one should test these in both LP64 and LLP64:

void foo (nullptr_t);
void foo (void *);
void foo (long);
void foo (int);

foo (nullptr);
foo (NULL);
foo ((void *)0);
foo (0);
foo (0L);
0 new messages