DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Floyd's Cycle Algorithm for Fraud Detection in Java Systems
  • Avoiding Pitfalls With Java Optional: Common Mistakes and How To Fix Them [Video]
  • Sliding Window
  • Linked List Popular Problems Vol. 1

Trending

  • Designing a Java Connector for Software Integrations
  • Mastering Advanced Aggregations in Spark SQL
  • Is Agile Right for Every Project? When To Use It and When To Avoid It
  • Developers Beware: Slopsquatting and Vibe Coding Can Increase Risk of AI-Powered Attacks

What Exactly Nullptr Is in C++?

In this article, we discuss some basics behind nullptr in C++, including what it is, why it's useful, and when we can use it.

By 
Vishal Chovatiya user avatar
Vishal Chovatiya
·
Apr. 16, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
49.5K Views

Join the DZone community and get the full member experience.

Join For Free

The answer to "What exactly nullptr is in C++?" would be a piece of cake for experienced C++ programmers and for those who are aware of Modern C++ (i.e. keyword). But nullptr is more than just a keyword in C++, and to explain that, I have written this article. But, before I jump into it, we will see issues with NULL. Then, we'll dive into the unsophisticated implementation of  nullptr and some use-cases of nullptr.

Why Do We Need Nullptr?

To distinguish between an integer, 0 (zero), i.e. NULL, and an actual null of type pointer.

Nullptr vs NULL

  • NULL is 0 (zero) i.e. integer constant zero with C-style typecast to void*, while nullptr is prvalue of type nullptr_t, which is an integer literal that evaluates to zero.
  • For those of you who believe that NULL is the same i.e. (void*)0 in C and C++. I would like to clarify that no it's not:
    • NULL - cppreference.com (C).
    • NULL - cppreference.com (C++)
  • C++ requires that macro NULL be defined as an integral constant expression, having the value of 0. So, unlike in C, NULL cannot be defined as (void *)0 in the C++ standard library.

Issues With NULL

Implicit Conversion

C++
 




xxxxxxxxxx
1


 
1
char *str = NULL; // Implicit conversion from void * to char *
2
int i = NULL;     // OK, but `i` is not pointer type



Function Calling Ambiguity

C
 




xxxxxxxxxx
1


 
1
void func(int) {}
2
void func(int*){}
3
void func(bool){}
4

          
5
func(NULL);     // Which one to call?



Compilation produces the following error:

Plain Text
 




xxxxxxxxxx
1


 
1
error: call to 'func' is ambiguous    func(NULL);    ^~~~
2
note: candidate function void func(bool){}                              ^
3
note: candidate function void func(int*){}                              ^
4
note: candidate function void func(int){}                              ^
5
1 error generated.
6
compiler exit status 1



Constructor Overload

C++
 




xxxxxxxxxx
1


 
1
struct String
2
{    String(uint32_t)    {   /* size of string */    }    String(const char*) {       /* string */        }
3
};
4

          
5
String s1( NULL );
6
String s2( 5 ); 



In such cases, you need explicit cast (i.e., String s((char*)0)).

Implementation of Unsophisticated Nullptr

nullptr is a subtle example of the Return Type Resolver idiom that automatically deduces a null pointer of the correct type depending upon the type of the instance it is assigning to.

Consider the following simplest and most unsophisticated nullptr implementation:

C++
 




xxxxxxxxxx
1


 
1
struct nullptr_t {    void operator&() const = delete;  // Can't take address of nullptr
2
    template<class T>    inline operator T*() const { return 0; }
3
    template<class C, class T>    inline operator T C::*() const { return 0; }
4
};
5
nullptr_t nullptr;



If the above code seems strange and weird to you, then I would suggest you go through my earlier article on advanced C++ concepts. The magic here is just the templatized conversion operator.

If you are into a more authoritative source, then, here is a concrete implementation of nullptr from LLVM header.

Use-Cases of Nullptr

C++
 




xxxxxxxxxx
1


 
1
struct C { void func(); };
2

          
3
int main(void)
4
{    int *ptr = nullptr;                // OK    void (C::*method_ptr)() = nullptr; // OK    nullptr_t n1, n2;    n1 = n2;    //nullptr_t *null = &n1;           // Address can't be taken.
5
}



As shown in the above example, when nullptr is being assigned to an integer pointer, a int type instantiation of the templatized conversion function is created. And same goes for method pointers too.

This way, by leveraging template functionality, we are actually creating the appropriate type of null pointer every time we do a new type assignment.

As nullptr is an integer literal with value zero, you can not able to use its address, which we accomplished by deleting and operator.

Function Calling Clarity With Nullptr

C++
 




xxxxxxxxxx
1


 
1
void func(int)   { /* ... */}
2
void func(int *) { /* ... */}
3
void func(bool)  { /* ... */}
4

          
5
func(nullptr);



Now, func( int* ) will be called as nullptr will implicitly be deduced to int*.

Typecasting on Nullptr_t

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.

Casting nullptr_t to an integral type holds true as long as destination type is large enough. Consider this:

C++
 




xxxxxxxxxx
1


 
1
// int ptr_not_ok = reinterpret_cast<int>(nullptr); // Not OK
2
long ptr_ok = reinterpret_cast<long long>(nullptr); // OK



A reinterpret_cast cannot convert nullptr_t to any pointer type. Use static_cast instead.

C++
 




xxxxxxxxxx
1


 
1
void func(int*)    { /*...*/ }
2
void func(double*) { /*...*/ }
3

          
4
func(nullptr);                            // compilation error, ambiguous call!
5

          
6
// func(reinterpret_cast<int*>(nullptr)); // error: invalid cast from type 'std::nullptr_t' to type 'int*'
7
func(static_cast<int*>(nullptr));         // OK



nullptr is implicitly convertible to any pointer type so explicit conversion with static_cast is only valid.

Nullptr_t Is Comparable

C++
 




xxxxxxxxxx
1


 
1
int *ptr = nullptr;
2
if (ptr == 0);          // OK
3
if (ptr <= nullptr);    // OK        
4

          
5
int a = 0;
6
if (a == nullptr);      // error: invalid operands of types 'int' and 'std::nullptr_t' to binary 'operator=='


From Wikipedia: - …null pointer constant: nullptr. It is of type nullptr_t, which is implicitly convertible and comparable to any pointer type or pointer-to-member type.
- It is not implicitly convertible or comparable to integral types, except for bool.

C++
 




xxxxxxxxxx
1


 
1
const int a = 0;
2
if (a == nullptr); // OK
3

          
4
const int b = 5;
5
if (b == nullptr); // error: invalid operands of types 'const int' and 'std::nullptr_t' to binary 'operator=='



Template-Argument Is of Type std::nullptr_t

C++
 




xxxxxxxxxx
1


 
1
template <typename T>
2
void ptr_func(T *t) {}
3

          
4
ptr_func(nullptr);         // Can not deduce T



As discussed earlier, Return Type Resolver needs an assignee to deduce the type.

C++
 




xxxxxxxxxx
1


 
1
template <typename T>
2
void val_func(T t) {}
3

          
4
val_func(nullptr);         // deduces T = nullptr_t
5
val_func((int*)nullptr);   // deduces T = int*, prefer static_cast though



Conversion to Bool From Nullptr_t

From cppreference:
In the context of a direct-initialization, a bool object may be initialized from a prvalue of type std::nullptr_t, including nullptr. The resulting value is false. However, this is not considered to be an implicit conversion.

The conversion is only allowed for direct-initialization — not copy-intialization, which includes the case for passing an argument to a function by value. e.g.

C++
 




xxxxxxxxxx
1


 
1
bool b1 = nullptr; // Not OK
2
bool b2 {nullptr}; // OK
3

          
4
void func(bool){}
5

          
6
func(nullptr);     // Not OK, need to do func(static_cast<bool>(nullptr));



Misc

C++
 




xxxxxxxxxx
1


 
1
typeid(nullptr);                            // OK
2
throw nullptr;                              // OK
3
char *ptr = expr ? nullptr : nullptr;       // OK
4
// char *ptr1 = expr ? 0 : nullptr;         // Not OK, types are not compatible
5
static_assert(sizeof(NULL) == sizeof(nullptr_t));
6

          



Summary by FAQs

When was nullptr introduced?

C++11

Is nullptr a keyword or an instance of a type std::nullptr_t?

Both true and false are keywords and literals, as they have a type ( bool ). nullptr is a pointer literal of type std::nullptr_t, and it's a prvalue (i.e. pure rvalue, you cannot take the address of it using &). For more.

What are the advantages of using nullptr?

  • No function calling ambiguity between overload sets.
  • You can do template specialization with nullptr_t.
  • Code will become more safe, intuitive, and expressive. if (ptr == nullptr); rather than if (ptr == 0);.

Is NULL in C++ equal to nullptr from C++11?

Not at all. The following line does not even compile:

cout<<is_same_v<nullptr, NULL><<endl;

Can I convert nullptr to bool?

Yes. But only if you use direct-initialization. i.e. bool is_false{nullptr};. Otherwise, you need to use static_cast.

How is nullptr defined?

It's just the templatized conversion operator known as Return Type Resolver.


References

You can find similar resources here, here, and in nullptr proposal(N2431); however, this post will walk you through the ins and outs of the spec step-by-step in a more friendly way so that you come away with a full understanding of the concept without any needless confusion

Pointer (computer programming)

Published at DZone with permission of Vishal Chovatiya. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Floyd's Cycle Algorithm for Fraud Detection in Java Systems
  • Avoiding Pitfalls With Java Optional: Common Mistakes and How To Fix Them [Video]
  • Sliding Window
  • Linked List Popular Problems Vol. 1

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!