To recap:
- A
shared_ptr
contains a pointer to the managed object. - A
shared_ptr
contains 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
.
CodePudding user response:
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.
CodePudding user response:
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.