The answer to "What exactly nullptr is in C++?" would be a piece of cake for experienced C++ eyes & for those who are aware of i.e. keyword. But nullptr is more than just a keyword in C++ & to explain that, I have written this article. But before jump-into it, we will see issues with NULL & then we'll dive into the unsophisticated implementation of nullptr & some use-cases of nullptr. Modern C++ /!\: Originally published @ . www.vishalchovatiya.com This article is more or less the same thing which you can find , & in but in a bit organized & simplified way. Note: here here nullptr proposal(N2431) Why do we need nullptr? To distinguish between an integer 0(zero) i.e. NULL & actual null of type pointer. nullptr vs NULL NULL is 0(zero) i.e. with to void*, while nullptr is of type nullptr_t which is . integer constant zero C-style typecast prvalue integer literal evaluates to zero For those of you who believe that NULL is same i.e. (void*)0 in C & C++. I would like to clarify that no it's not: (C) NULL - cppreference.com (C++) NULL - cppreference.com C++ requires that macro NULL to 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 1️⃣ Implicit conversion *str = ; i = ; char NULL // Implicit conversion from void * to char * int NULL // OK, but `i` is not pointer type 2️⃣ Function calling ambiguity {} {} {} func( ); void func ( ) int void func ( *) int void func ( ) bool NULL // Which one to call? Compilation produces the following error: error: call to ; ^~~~ note: {} ^ note: {} ^ note: {} ^ error generated. compiler status 'func' is ambiguous func ( ) NULL candidate function void func ( ) bool candidate function void func ( *) int candidate function void func ( ) int 1 exit 1 3️⃣ Constructor overload String( ) { } String( *) { } }; ; ; { struct String uint32_t /* size of string */ const char /* string */ String s1 ( ) NULL 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 idiom to automatically deduce a null pointer of the correct type depending upon the type of the instance it is assigning to. Return Type Resolver Consider the following simplest & unsophisticated nullptr implementation: &() = ; < ; } < :*() { ; } }; ; { struct nullptr_t void operator const delete // Can't take address of nullptr template > *() { class T inline operator T const return 0 template , > : class C class T inline operator T C const return 0 nullptr_t nullptr If the above code seems strange & weird to you(although it should not), then I would suggest you go through my earlier article on . The magic here is just the templatized conversion operator. advanced C++ concepts If you are into a more authoritative source, then, here is a . concrete implementation of nullptr from LLVM header Use-cases of nullptr ; }; { *ptr = ; (C::*method_ptr)() = ; n1, n2; n1 = n2; } { struct C void func () int main ( ) void int nullptr // OK void nullptr // OK nullptr_t //nullptr_t *null = &n1; // Address can't be taken. 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 with value zero, you can not able to use its address which we accomplished by deleting & operator. integer literal 1️⃣ Function calling clarity with nullptr { } { } { } func( ); void func ( ) int /* ... */ void func ( *) int /* ... */ void func ( ) bool /* ... */ nullptr Now, func( int* ) will be called as nullptr will implicitly be deduced to int*. 2️⃣ 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: ptr_ok = < >( ); // int ptr_not_ok = reinterpret_cast<int>(nullptr); // Not OK long reinterpret_cast long long nullptr // OK A reinterpret_cast cannot convert nullptr_t to any pointer type. Use static_cast instead. { } { } func( ); func( < *>( )); void func ( *) int /*...*/ void func ( *) double /*...*/ nullptr // compilation error, ambiguous call! // func(reinterpret_cast<int*>(nullptr)); // error: invalid cast from type 'std::nullptr_t' to type 'int*' static_cast int nullptr // OK nullptr is implicitly convertible to any pointer type so explicit conversion with static_cast is only valid. 3️⃣ nullptr_t is comparable *ptr = ; (ptr == ); (ptr <= ); a = ; (a == ); int nullptr if 0 // OK if nullptr // OK int 0 if nullptr // error: invalid operands of types 'int' and 'std::nullptr_t' to binary 'operator==' From : - …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. Wikipedia a = ; (a == ); b = ; (b == ); const int 0 if nullptr // OK const int 5 if nullptr // error: invalid operands of types 'const int' and 'std::nullptr_t' to binary 'operator==' 4️⃣ Template-argument is of type std::nullptr_t < T> {} ptr_func( ); template typename void ptr_func (T *t) nullptr // Can not deduce T As discussed earlier, needs an assignee to deduce the type. Return Type Resolver < T> {} val_func( ); val_func(( *) ); template typename void val_func (T t) nullptr // deduces T = nullptr_t int nullptr // deduces T = int*, prefer static_cast though 5️⃣ Conversion to bool from nullptr_t From : - In the context of a , a bool object may be initialized from a prvalue of type , including nullptr. The resulting value is false. However, this is not considered to be an implicit conversion. cppreference direct-initialization std::nullptr_t The conversion is only allowed for , but not , which including the case for passing an argument to a function by value. e.g. direct-initialization copy-intialization b1 = ; b2 { }; {} func( ); bool nullptr // Not OK bool nullptr // OK void func ( ) bool nullptr // Not OK, need to do func(static_cast<bool>(nullptr)); 6️⃣ Misc ( ); ; *ptr = expr ? : ; ( ( ) == ( )); typeid nullptr // OK throw nullptr // OK char nullptr nullptr // OK // char *ptr1 = expr ? 0 : nullptr; // Not OK, types are not compatible static_assert sizeof NULL sizeof nullptr_t 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 & literals, as they have a type ( bool ). nullptr is a of type std::nullptr_t, & it's a prvalue (i.e. pure , you cannot take the address of it using &). . pointer literal rvalue 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 & 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: <<is_same_v< , ><< ; cout nullptr NULL endl Can I convert nullptr to bool? Yes. But only if you . i.e. bool is_false{nullptr};. Else need to use static_cast. direct-initialization How is nullptr defined? It's just the templatized conversion operator known as . Return Type Resolver Have any suggestions, query or wants to say `Hi`? 🖱️ Take the Pressure Off, you are just a click away. Previosuly published at http://www.vishalchovatiya.com/what-exactly-nullptr-is-in-cpp/