'Why does a null but non-empty std::shared_ptr fail an if() statement?
To recap:
- A
shared_ptrcontains a pointer to the managed object. - A
shared_ptrcontains a reference to a control block which is shared amongst shared_ptrs. - In case ptr to managed object = nullptr -> shared_ptr is considered
null - In case ptr to control block = nullptr -> shared_ptr is considered
empty
What's interesting is you can create null but non-empty shared_pts by casting nullptr to reference type like so (example borrowed from another thread.
#include <memory>
#include <iostream>
int main()
{
std::cout << "std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))" << std::endl;
{
std::shared_ptr<int> ptr1(static_cast<int*>(nullptr));
std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
std::shared_ptr<int> ptr2 = ptr1;
std::cout << "\tuse count after copying ptr: " << ptr1.use_count() << std::endl;
std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
}
std::cout << std::endl;
}
This will output the following:
std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))
use count before copying ptr: 1
use count after copying ptr: 2
ptr1 is null
As you can see the shared_ptr fails the if()-statement and is considered null. But how is that possible when obviously there must be a non-null pointer to the task control block inside the shared_ptr object? I would have thought that only objects which equate to 0 memory (all fields set to 0) are considered null.
EDIT: I was actually confused because I didn't know about conversion operators. I just discovered them now and it totally makes sense that when conversion to bool is triggered we can just return the stored pointer.
Solution 1:[1]
I would have thought that only objects which equate to 0 memory (all fields set to 0) are considered null
There us no such thing as "null object" in C++.
A built-in pointer (including a pointer-to-member) can be a null pointer. Null pointers do not have to be represented with all zero bits. A character can be a null character. A number can be zero (not "null"). There are few other null things in C++, like null statements and null preprocessor directives, but those are not objects.
shared_ptr objects are not called "null pointers" by the C++ standard (they are not pointers, only built-in pointers are pointers). The standard only says things like r.get() == nullptr to express the idea of a shared_ptr not pointing to an object. Colloquially, in this case we may say that "the shared pointer is null". This usage is non-standard, and it has nothing to do with zero or non-zero bits inside a shared_ptr representation.
A shared_ptr is convertible to bool and this conversion enables things like r ? .. : ... and if (r) .... The conversion operator returns exactly get() == nullptr and not anything about zero or non-zero bits inside a shared_ptr representation.
Solution 2:[2]
The use count is a property of a shared_ptr. But asking about that property is different from asking whether the pointer points to a live T. That question is purely about the pointer the shared_ptr instance holds, and that's the question explicit operator bool answers.
Indeed, the pointer being held by a shared_ptr<T> can be entirely independent of the object being managed. You can associate a managed state object with basically any pointer you like. Accessing the shared_ptr<T> will access the T it currently stores, but this does not have to be a pointer to the object being managed. So trying to combine the two questions just doesn't make sense.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | n. 1.8e9-where's-my-share m. |
| Solution 2 |
