In a couple of my older code projects when I had never heard of smart pointers, whenever I needed to check whether the pointer still pointed to a valid object, I would always do something like this...
object * meh = new object; if(meh) meh->member;
Or when I needed to delete the object safely, something like this
if(meh) { delete meh; meh = 0; }
Well, now I have learned about the problems that can arise from using objects and pointers in boolean expressions both with literal numbers, the hard way :. And now I've also learned of the not so new but pretty cool feature of C++, the nullptr
keyword. But now I'm curious.
I've already gone through and revised most of my code so that, for example, when deleting objects I now write
if(meh) { delete meh; meh = nullptr; }
Now I'm wondering about the boolean. When you pass just say an int into an if statement like this,
int meh; if(meh)
Then it implicitly checks for zero without you needing to write it.
if(meh == 0) // does the exact same check
Now, will C++ do the same for pointers? If pass in a char * like this to an if statement?
char * meh; if(meh)
Then will it implicitly compare it with nullptr? Because of how long I have been writing these ifs like this, it is second nature at this point to check if the pointers valid before using by typing if (object *) and then calling its members. If this is not the functionality why not? Too difficult to implement? Would solve some problems by removing yet another tiny way you could mess up your code.
No, you can't.
A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of pointer to object or pointer to function type." Says nothing about the address a null pointer value points to.
In C++11 and beyond, a pointer that is ==NULL will also ==nullptr and vice versa. Uses of NULL other than comparing with a pointer (like using it to represent the nul byte at the end of a string) won't work with nullptr .
Use Pointer Value as Condition to Check if Pointer Is NULL in C++ Null pointers are evaluated as false when they are used in logical expressions. Thus, we can put a given pointer in the if statement condition to check if it's null.
In C, anything that's not 0 is true. So, you certainly can use:
if (ptrToObject) ptrToObject->doSomething();
to safely dereference pointers.
C++11 changes the game a bit, nullptr_t
is a type of which nullptr
is an instance; the representation of nullptr_t
is implementation specific. So a compiler may define nullptr_t
however it wants. It need only make sure it can enforce proper restriction on the casting of a nullptr_t
to different types--of which boolean is allowed--and make sure it can distinguish between a nullptr_t
and 0.
So nullptr
will be properly and implicitly cast to the boolean false
so long as the compiler follows the C++11 language specification. And the above snippet still works.
If you delete a referenced object, nothing changes.
delete ptrToObject; assert(ptrToObject); ptrToObject = nullptr; assert(!ptrToObject);
Because of how long I have been writing these ifs like this, it is second nature at this point to check if the pointers valid before using by typing if (object *) and then calling it's members.
No. Please maintain a proper graph of objects (preferably using unique/smart pointers). As pointed out, there's no way to determine if a pointer that is not nullptr
points to a valid object or not. The onus is on you to maintain the lifecycle anyway.. this is why the pointer wrappers exist in the first place.
In fact, because the life-cycle of shared and weak pointers are well defined, they have syntactic sugar that lets you use them the way you want to use bare pointers, where valid pointers have a value and all others are nullptr
:
Shared
#include <iostream> #include <memory> void report(std::shared_ptr<int> ptr) { if (ptr) { std::cout << "*ptr=" << *ptr << "\n"; } else { std::cout << "ptr is not a valid pointer.\n"; } } int main() { std::shared_ptr<int> ptr; report(ptr); ptr = std::make_shared<int>(7); report(ptr); }
Weak
#include <iostream> #include <memory> void observe(std::weak_ptr<int> weak) { if (auto observe = weak.lock()) { std::cout << "\tobserve() able to lock weak_ptr<>, value=" << *observe << "\n"; } else { std::cout << "\tobserve() unable to lock weak_ptr<>\n"; } } int main() { std::weak_ptr<int> weak; std::cout << "weak_ptr<> not yet initialized\n"; observe(weak); { auto shared = std::make_shared<int>(42); weak = shared; std::cout << "weak_ptr<> initialized with shared_ptr.\n"; observe(weak); } std::cout << "shared_ptr<> has been destructed due to scope exit.\n"; observe(weak); }
Now, will C++ do the same for pointers? If pass in a char * like this to an if statement?
So to answer the question: with bare pointers, no. With wrapped pointers, yes.
Wrap your pointers, folks.
It's not possible to test whether a pointer points to a valid object or not. If the pointer is not null but does not point to a valid object, then using the pointer causes undefined behaviour. To avoid this sort of error, the onus is on you to be careful with the lifetime of objects being pointed to; and the smart pointer classes help with this task.
If meh
is a raw pointer then there is no difference whatsoever between if (meh)
and if (meh != 0)
and if (meh != nullptr)
. They all proceed iff the pointer is not null.
There is an implicit conversion from the literal 0
to nullptr
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With