class myClass
{
public:
void fun()
{
async_do( [this](int j)
{
i+=j;
} );
}
private:
int i=9;
}
int main()
{
std::shared_ptr<myClass> obj = std::make_shared<myClass>();
obj->fun();
obj->reset();
return 0;
}
The code above, when we call fun()
, it will call async_do()
, async_do()
will return immediately. When the async operation is completed, the lambda function will be called. But, while this async operation is still running, the object could be destroyed. When the lambda is called, the object doesn't exist anymore. What should I do in this callback function in this situation?
Thank you for your help.
weak_from_this
is useful in this case.
Use case: when you need to create a callback but caller of the callback doesn't know the lifetime of this
and the design allows this
destructed before callback gets invoked.
The difference between shared_from_this()
is that weak_from_this()
won't keep the instance alive but only try to access it when needed. It is important to note that capturing std::shared_ptr
might prolong the lifetime of a instance until callback is released. It might not fit all the use cases.
Eg: Requires only invoking the most recent instance instead of holding all the instances and do not want to keep other instance.
#include <fmt/core.h>
#include <fmt/format.h>
#include <functional>
#include <memory>
using Callback = std::function<void(int)>;
class myClass : public std::enable_shared_from_this<myClass>
{
public:
Callback createWeakCallback()
{
return [weak_ref = weak_from_this()](int j) {
auto strong_ref = weak_ref.lock();
if (nullptr == strong_ref){
fmt::print("This is dead.\n");
return;
}
// use `strong_ref` as `this`
strong_ref->add(j);
};
}
Callback createStrongCallback()
{
return [shared = shared_from_this()](int j) {
shared->add(j);
};
}
myClass(int val): i(val){}
~myClass(){
fmt::print("dtor, i:{}\n", i);
}
void add(int j){
i+=j;
fmt::print("i: {}\n", i);
}
private:
int i=9;
};
int main()
{
std::shared_ptr<myClass> obj = std::make_shared<myClass>(0);
Callback cb = obj->createWeakCallback();
cb(6);
obj.reset();
cb(5);
{ // Scope of strongCb
Callback strongCb;
{
std::shared_ptr<myClass> obj = std::make_shared<myClass>(100);
strongCb = obj->createStrongCallback();
strongCb(10); // <-- still alive
fmt::print("End of obj first std::shraed_ptr scope\n");
}
fmt::print("End of strongCb\n");
} // <-- obj get destructed here
return 0;
}
Output:
i: 6
dtor, i:6
This is dead.
i: 110
End of obj first std::shraed_ptr scope
End of strongCb
dtor, i:110