Extend facility life
Lambdas can grab common pointers before this , so the object will not die, although there is at least one lambda.
class Foo : public std::enable_shared_from_this<Foo> { public: Foo(const std::string& i_name) : name(i_name) {} std::function<void()> GetPrinter() { std::shared_ptr<Foo> that = shared_from_this(); return [that]() { std::cout << that->name << std::endl; }; } std::string name; };
http://ideone.com/Ucm2p8
Usually this is not a good solution, since the lifetime of the object here is very implicit. This is a very simple way to create circular links between objects.
Tracking Object Lifetime
Lambdas can track the lifetime of a captured object and use the object only if it is still alive.
class Foo : public std::enable_shared_from_this<Foo> { public: Foo(const std::string& i_name) : name(i_name) {} std::function<void()> GetPrinter() { std::weak_ptr<Foo> weak_this = shared_from_this(); return [weak_this]() { auto that = weak_this.lock(); if (!that) { std::cout << "The object is already dead" << std::endl; return; } std::cout << that->name << std::endl; }; } std::string name; };
http://ideone.com/Wi6O11
Life expectancy of an object without common pointers
As stated in hvd, we cannot always be sure that the object is controlled by shared_ptr . In that case, I would suggest using the following lifetime_tracker . It is autonomous and does not affect the way of controlling the lifetime of an object.
struct lifetime_tracker { private: struct shared_state { std::uint32_t count : 31; std::uint32_t dead : 1; }; public: struct monitor { monitor() : state(nullptr) {} monitor(shared_state *i_state) : state(i_state) { if (state) ++state->count; } monitor(const monitor& t) : state(t.state) { if (state) ++state->count; } monitor& operator=(monitor t) { std::swap(state, t.state); return *this; } ~monitor() { if (state) { --state->count; if (state->count == 0 && state->dead) delete state; } } bool alive() const { return state && !state->dead; } private: shared_state *state; }; public: lifetime_tracker() : state(new shared_state()) {} lifetime_tracker(const lifetime_tracker&) : state(new shared_state()) {} lifetime_tracker& operator=(const lifetime_tracker& t) { return *this; } ~lifetime_tracker() { if (state->count == 0) delete state; else state->dead = 1; } monitor get_monitor() const { return monitor(state); } private: shared_state *state; };
Usage example
class Foo { public: Foo(const std::string& i_name) : name(i_name) {} std::function<void()> GetPrinter() { auto monitor = tracker.get_monitor(); return [this, monitor]() { if (!monitor.alive()) { std::cout << "The object is already dead" << std::endl; return; } std::cout << this->name << std::endl; }; } private: lifetime_tracker tracker; std::string name; };
source share