Consider the following code:
#include <iostream>
#include <memory>
using namespace std;
class T;
std::weak_ptr<T> wptr;
class T
{
public:
T() { }
~T() {
std::cout << "in dtor" << std::endl;
std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
}
};
int main() {
{
auto ptr = std::make_shared<T>();
wptr = ptr;
std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
}
return 0;
}
In this code, I was trying to find out if weak_ptr
s are expired in the objects destruction phase. It seems so. The output is:
not expired
in dtor
expired
I used gcc-5.1 with ideone.
Now, I have another problem. I couldn't find any documentation stating that this is the standard behavior. Is it guaranteed to work this way, always?
Using make_shared like that will create an object with the default constructor you provided.
After the anonymous scope in the main. The shared ptr will be deleted.
.
This means that your object will call its destructor after the destruction of the last shared ptr has started. The output:
is the expected behavior.
No. Indeed, it's underspecified in the standard, as raised by LWG issue 2751.
The current wording for
~shared_ptr()
as linked above simply states that the deleter is invoked, with a non-normative note that the number of instances that share ownership is decreased.While the intent is probably that
weak.expired()
when the deleter is called, it's questionable to rely on this. It's really only reasonable to state with confidence that theshared_ptr
no longer shares ownership after it's been destroyed - asking that question during destruction is a bit odd.Not the standard itself but:
http://en.cppreference.com/w/cpp/memory/weak_ptr/expired
So it becomes a question of weather
use_count
is set to 0 before or after deletion. Now there's a not on this in a draft of the standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf [page 566 20.9.2.2.2]A
weak_ptr
expires when there are no moreshared_ptr
s referring to the object.When (immediately after) the last
shared_ptr
stops referring to the object it's destroyed.At this point there are no
shared_ptr
s referring to it, so anyweak_ptr
has expired.The object's destructor is now invoked and if it has separate storage (i.e. wasn't created with
make_shared
) its storage is deallocated.The control block, where the reference count and raw pointer and delete function are stored, persists if there are any
weak_ptr
s referring to it. When the lastweak_ptr
stops referring to it, also the control block is destroyed and deallocated. I.e.,shared_ptr
instances keep the object itself alive, along with its control block, whileweak_ptr
instances keep the control block alive.