Here is a minimal example to reproduce:
source code:
#include <memory>
#include <iostream>
class A : public std::enable_shared_from_this<A>
{
public:
A(std::weak_ptr<A> up) : up_(up)
{
std::cout << "A" << " has up_? " <<
((up_.lock()) ? "yes" : "no")
<< std::endl;
}
void grow()
{
if (dp_)
dp_->grow();
else
dp_ = std::make_shared<A>(weak_from_this());
}
private:
std::weak_ptr<A> up_;
std::shared_ptr<A> dp_;
};
int main()
{
auto wp = std::weak_ptr<A>();
A a(wp);
for (int i = 0; i < 3; ++i)
{
a.grow();
}
return 0;
}
original log:
clang++ minimal.cpp && ./a.out
A has up_? no
A has up_? no
A has up_? yes
A has up_? yes
desired behavior:
clang++ minimal.cpp && ./a.out
A has up_? no
A has up_? yes
A has up_? yes
A has up_? yes
Actually I want to know why the second line in the original output says 'no'? I think when we create the object of type A for the first time, (precisely after its construction finishes, and before we call grow()
on it), we have a valid object that we can pass references to to wherever we want, don't we?
From cppreference, about std::enable_shared_from_this::weak_from_this
Returns a
std::weak_ptr<T>
that tracks ownership of*this
by all existingstd::shared_ptr
that refer to*this
.
Meanwhile
A a(wp);
This is not an object that is tracked by any shared_ptr
. It's a plain object with automatic storage duration. If you want weak_from_this
to work, there must be a shared_ptr
tracking the first object.