Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How std::enable_shared_from_this::shared_from_this works

Tags:

I just cannot understand how std::enable_shared_from_this::shared_from_this returns a shared pinter that shared ownership with existing pointer. In other words you do this:

std::shared_ptr<Foo> getFoo() { return shared_from_this(); } 

So when you call getFoo how does exactly it get what is the other shared_ptr to share the ownership with and not to create a separate shared_ptr that owns the same this.

I need to understand this to be able to understand how to create shared_ptr from some object that all increase the same ref count and not initialize separate shared_ptrs.

like image 657
Narek Avatar asked Dec 03 '15 08:12

Narek


Video Answer


1 Answers

enable_shared_from_this<T> has a weak_ptr<T> data member. The shared_ptr<T> constructor can detect if T is derived from enable_shared_from_this<T>. If it is, the shared_ptr<T> constructor will assign *this (which is the shared_ptr<T>) to the weak_ptr data member in enable_shared_from_this<T>. shared_from_this() can then create a shared_ptr<T> from the weak_ptr<T>.

Example of a possible implementation:

template<class D> class enable_shared_from_this { protected:     constexpr enable_shared_from_this() { }     enable_shared_from_this(enable_shared_from_this const&) { }     enable_shared_from_this& operator=(enable_shared_from_this const&) {         return *this;     }  public:     shared_ptr<T> shared_from_this() { return self_.lock(); }     shared_ptr<T const> shared_from_this() const { return self_.lock(); }  private:     weak_ptr<D> self_;      friend shared_ptr<D>; };  template<typename T> shared_ptr<T>::shared_ptr(T* ptr) {     // ...     // Code that creates control block goes here.     // ...      // NOTE: This if check is pseudo-code. Won't compile. There's a few     // issues not being taken in to account that would make this example     // rather noisy.     if (is_base_of<enable_shared_from_this<T>, T>::value) {         enable_shared_from_this<T>& base = *ptr;         base.self_ = *this;     } } 
like image 116
Simple Avatar answered Sep 24 '22 19:09

Simple