Bind a class member function and a valid class object pointer to boost::function<>fn. What may happen if invoking the fn
after the object which the pointer pointed to has been destroyed?
Are there some potential problems that I should be aware of?
Domo code snappet:
class CTest
{
public:
int demo(void){}
};
int main()
{
boost::function<int(void)> fn;
{
CTest ins;
fn = boost::bind(&CTest::demo, &ins);
}
fn();
}
Edited(https://godbolt.org/z/r8EK1G)
Quoted from the comment of j6t
One way to do that is to pass the object by value, not a pointer to the object. Then a copy of the object would be used during the invocation fn(). I think there is still a problem that the object 'tes' is out of scope.So passing value is not a good method. :
#include<functional>
#include<iostream>
class CTest
{
public:
int demo(void){std::cout << "do better" << std::endl;return 0;}
};
template <class T=CTest>
std::function<int(void)> bindWarp(T obj, int (T::*mem_func)(void))
{
return std::bind(mem_func, obj);
}
int main()
{
std::function<int(void)> fn;
{
CTest tes;
fn = bindWarp(tes, &CTest::demo);
}
fn(); //I think there is still a problem that the object 'tes' is out of scope.So passing value is not a good method.
}
You need to ensure that the target object's lifetime exceeds the function object's lifetime. This is easier to express in an obvious way with a lambda function instead of bind. The lambda can explicitely capture the object 'by-value':
std::function<int(void)> fn;
{
CTest tes;
fn = [tes] { tes.demo(); };
}
fn();
With std::bind you can also explicitely express this, and avoid a copy, by writing:
fn = std::bind(&CTest::demo, std::move(tes));
You could also pass to bind by-value instead of by-reference but I would prefer the two constructs above because they make the intention very clear (copying the object or transfering ownership).
If you want to avoid a copy or transfer of ownership, you may use a shared pointer with the lambda instead. You could even go as far as using a weak_ptr
within the lambda, so the object is not kept alive for it.
See also this very helpful discussion about the details of binds & lambdas in modern C++: https://stackoverflow.com/a/17545183/21974