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?
std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.
weak_ptr::lockCreates a new std::shared_ptr that shares ownership of the managed object. If there is no managed object, i.e. *this is empty, then the returned shared_ptr also is empty.
To implement weak_ptr , the "counter" object stores two different counters: The "use count" is the number of shared_ptr instances pointing to the object. The "weak count" is the number of weak_ptr instances pointing to the object, plus one if the "use count" is still > 0.
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?
No. Indeed, it's underspecified in the standard, as raised by LWG issue 2751.
The C++14 standard contains no language that guarantees the deleter run by a
shared_ptr
will see all associatedweak_ptr
instances as expired. For example, the standard doesn't appear to guarantee that the assertion in the following snippet won't fire:std::weak_ptr<Foo> weak; std::shared_ptr<Foo> strong{ new Foo, [&weak] (Foo* f) { assert(weak.expired()); delete f; }, }; weak = strong; strong.reset();
It seems clear that the intent is that associated
weak_ptr
s are expired, because otherwiseshared_ptr
deleters could resurrect a reference to an object that is being deleted.Suggested fix: 23.11.3.2 [util.smartptr.shared.dest] should specify that the decrease in
use_count()
caused by the destructor is sequenced before the call to the deleter or the call todelete p
.
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 the shared_ptr
no longer shares ownership after it's been destroyed - asking that question during destruction is a bit odd.
Using make_shared like that will create an object with the default constructor you provided.
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
Constructs an object of type T and wraps it in a
std::shared_ptr
using args as the parameter list for the constructor of T. The object is constructed as if by the expression (std::make_shared)
After the anonymous scope in the main. The shared ptr will be deleted.
The object is destroyed and its memory deallocated when either of the following happens:
the last remaining shared_ptr owning the object is destroyed; (std::shared_ptr)
.
The destructor of shared_ptr decrements the number of shared owners of the control block. If that counter reaches zero, the control block calls the destructor of the managed object. The control block does not deallocate itself until the std::weak_ptr counter reaches zero as well. std::shared_ptr Implementation notes
This means that your object will call its destructor after the destruction of the last shared ptr has started. The output:
not expired
in dtor
expired
is the expected behavior.
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