What Are the Advantages of Using Nullptr

What are the advantages of using nullptr?

In that code, there doesn't seem to be an advantage. But consider the following overloaded functions:

void f(char const *ptr);
void f(int v);

f(NULL); //which function will be called?

Which function will be called? Of course, the intention here is to call f(char const *), but in reality f(int) will be called! That is a big problem1, isn't it?

So, the solution to such problems is to use nullptr:

f(nullptr); //first function is called

Of course, that is not the only advantage of nullptr. Here is another:

template<typename T, T *ptr>
struct something{}; //primary template

template<>
struct something<nullptr_t, nullptr>{}; //partial specialization for nullptr

Since in template, the type of nullptr is deduced as nullptr_t, so you can write this:

template<typename T>
void f(T *ptr); //function to handle non-nullptr argument

void f(nullptr_t); //an overload to handle nullptr argument!!!

1. In C++, NULL is defined as #define NULL 0, so it is basically int, that is why f(int) is called.

What are the advantages/disadvantages of std::optional over nullptr?

The sole job of std::optional is to extend the type domain by an additional "null" value. Every pointer type T* already has a value considered "null" - nulltpr.

Thus, it's not a good idea to compare those two directly, because they answer different questions. Sometimes it's important to differentiate between "no result" and "null result"1 (which is one of the possible interpretations), sometimes it's not. You should use whichever fits your needs.

Now if the only reason the code returned a pointer was to make use of the implicit pointer nullability, then the proper solution would be to change it to return std::optional<SomePointer> (or perhaps std::optional<std::reference_wrapper<SomePointer>>) instead, but that's not what you asked about.


1 Of course at this point it's also worthwhile to consider something like e.g. struct NoResult {}; using Result = std::variant<NoResult, SomePointer*>; to make it even more explicit.

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*).

Benefits of Null Safety

I will assume that you come from Java, you already looked at some explanations somewhere else and did not fully understand them. Therefore, I will not try to give you a comprehensive explanation (which you can find elsewhere) but instead I will try to make clear the core idea of null pointer safety.

There are two points that, if you understand them, should make it clear enough. First, there is the idea of having two separate types to represent what you would model as a single type in Java: nullable ones and not nullable ones. To give you an example, while in Java you put a string in a String object, without caring if the string can be null or not, in Kotlin you have two types: String? and String. The first accepts null values (like the Java equivalent) but the second does not. So you can have null values in types with a ? (like String? or Int?) but there are a lot of restrictions on what you can do with those: basically you are restricted to the things you can do with a null, because, after all, the variable could be holding a null value. So no calling of method on it, for instance. So, while in Java you could call a method on it and have a NullPointerException sometimes, in Kotlin you cannot call any methods. And this is not because of some silent behavior of Kotlin, it’s much simpler than that: the compiler won’t let you. Try and you will see that the program does not compile. If the variable was of type String instead of String? then Kotlin would allow you to call methods from it.

So, basically, no null pointer exceptions because you can never call a method on an object variable that could be null.

But then, sometimes the variable is not null: so how could you call the method on the variable in those cases where the variable is not null? Again, the answer is simple: you have to check it. I mean, you have to use an if instruction (explicitly or implicitly) that will check if the variable is null or not. Something like “if (myVariable != null) {call method on variable}”. So, as you can see, the Kotlin compiler is clever enough to see that you used an if instruction that guarantees that the variable is not null, so it will let you call methods on the variable in the block between { and }. In other words, if your variable is of type String? but you are inside an if block where you checked that the variable is not null, Kotlin will treat it like a variable of type String instead of String?

When you speak about

some part the code which silently won't be executed

I am guessing you are thinking about some operators that have an implicit if inside of them, like the ?. operator. If you write

myVariable?.call()

it means roughly

if (myVariable != null) { myVariable.call()}

So, indeed, if the variable is null, it will “fail” silently. But this is not different than Java if you use the same kind of if. In other words, nothing will happen if the variable is null because you explicitly coded it to behave like that.

using nullptr instead of NULL when mixing C and C++

Yes. nullptr is comparable to and equivalent to a null pointer of any other pointer type.

What is the difference between nullptr and nullptr_t in C++?

nullptr is the constant, nullptr_t is its type. Use each one in contexts where you need respectively a null pointer, or the type of a null pointer.

Using nullptr in API function calls?

Yes, you can safely use nullptr anywhere you use NULL.

NULL expanded to an integer constant expression with the value zero, which could then be converted to a null pointer value of any type. nullptr is "pointer literal" that does the exact same thing: it converts to a null pointer value of any type.

More information here.

Why is nullptr a part of the core language, but nullptr_t is a part of STL?

The proposal that introduced nullptr, N2431, indicates in section 1.1 that it was desirable to not force users to include a header in order to use nullptr.

It also remarks, "We do not expect to see much direct use of nullptr_t in real programs". Thus, it was considered preferable to add nullptr_t to the library rather than create a new keyword only to be used for this obscure purpose. In addition, if you don't want to include the header, you can always just write decltype(nullptr) yourself.



Related Topics



Leave a reply



Submit