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