std :: enable_shared_from_this :: shared_from_this如何工作

时间:2015-12-03 08:53:34

标签: c++ c++11 shared-ptr

我无法理解std::enable_shared_from_this::shared_from_this如何返回与现有指针共享所有权的共享pinter。换句话说,你做this

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

因此,当您致电getFoo时,与其他shared_ptr分享所有权的原因是什么,而不是创建拥有相同shared_ptr的单独this shared_ptr }。

我需要理解这一点,以便能够理解如何从某个对象创建shared_ptr,这些对象都会增加相同的引用计数而不会初始化单独的onCreate

2 个答案:

答案 0 :(得分:23)

enable_shared_from_this<T>weak_ptr<T>个数据成员。 shared_ptr<T>构造函数可以检测T是否派生自enable_shared_from_this<T>。如果是,shared_ptr<T>构造函数会将*thisshared_ptr<T>)分配给weak_ptr中的enable_shared_from_this<T>数据成员。然后,shared_from_this()可以从shared_ptr<T>创建weak_ptr<T>

可能的实施示例:

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;
    }
}

答案 1 :(得分:0)

我正在提交一种替代方法,其中EnabledSharedFromThis实现不会增加从其继承类的额外指针的开销。 这是一个非常粗糙的解决方案,我有兴趣了解一种更有效的实现EnabledSharedFromThis的解决方案。

#include <iostream>
#include <type_traits>
#include <map>
#include <memory>

using namespace std;

template<typename T>
struct EnableShareFromThis;

template<typename T>
struct Shr_ptr;

//SHARED POINTER implementation with lot of flaws :)
template<typename T>
struct Shr_ptr{

  //very brute approach to solving this problem.
  static map<T*, Shr_ptr<T>*> ENABLE_SHARE_STORE;

  protected:
    T* raw;
    int* ref;


  public:

    Shr_ptr():raw(nullptr), ref(nullptr){

      cout << "Shr_ptr...." << endl;

    }

    Shr_ptr(T* p, int* c):raw(p), ref(c){

      ++(*ref);
      cout << "Shr_ptr ctr with raw & ref..." << *c << endl;
    }

    Shr_ptr(T* p):raw(p), ref(new int(1)){

      if(std::is_base_of<EnableShareFromThis<T>, T>::value)
      {
        cout << "   is_base_of<EnableShareFromThis" << endl;

        ENABLE_SHARE_STORE.insert(make_pair(static_cast<T*>(raw), this)); 
      }
      cout << "Shr_ptr...param...ctr..ref=" << *ref << endl;
    }

    bool operator==(const Shr_ptr& rhs){

      return (raw == rhs.raw) && (*ref == *rhs.ref);
    }

    bool operator<(const Shr_ptr& rhs){

      return raw < rhs.raw && *ref < *rhs.ref;
    }

    Shr_ptr& operator=(const Shr_ptr& rhs){

      if(this == &rhs)
        return *this;

      raw = rhs.raw;
      ++(*rhs.ref);
      ref = rhs.ref;
      cout << "Shr_ptr...operator=....ref=" << *ref << endl;

      return *this;
    }

    Shr_ptr(const Shr_ptr& rhs){

      if(rhs.raw)
        raw = rhs.raw;
      if(rhs.ref)
      {
        ++(*rhs.ref);
        ref = rhs.ref;
        cout << "Shr_ptr...cpy ctr...ref=" << *ref <<  endl;
      }
    }

    Shr_ptr(Shr_ptr&& rhs){
      cout << "Shr_ptr...mv ctr...." << endl;
      if(rhs.raw)
      {
        raw = rhs.raw;
        rhs.raw = nullptr;
      }
      if(rhs.ref)
      {
        ++(*rhs.ref);
        ref = rhs.ref;
        cout << "Shr_ptr...mv ctr...ref=" << *ref <<  endl;
        rhs.ref = nullptr;
      }

    }

    T* operator->(){
      return raw;
    }

    T* get() const{return raw;}
    T* get() {return raw;}

    int use_count()
    {
      return *ref;
    }

    ~Shr_ptr()
    {
      cout << "~Shr_ptr ref=" << *ref << endl;
      --*ref;
      if(*ref==0)
      {
        Shr_ptr<T>::ENABLE_SHARE_STORE.erase(raw);
        delete raw;
        raw = nullptr;
      }
    }


};

template<typename T>
    map<T*, Shr_ptr<T>*> Shr_ptr<T>::ENABLE_SHARE_STORE;


template<typename T>
struct EnableShareFromThis{

  EnableShareFromThis()
  {
    cout << "EnableShareFromThis ctr..." << endl;
  }

  Shr_ptr<T> SharedFromThis() 
  {
      auto itr = Shr_ptr<T>::ENABLE_SHARE_STORE.find(static_cast< T*>(this));
      if (itr != Shr_ptr<T>::ENABLE_SHARE_STORE.end())
      {
        cout << "    SharedFromThis called....." << endl;
        return *itr->second;
      }

      return Shr_ptr<T>(static_cast< T*>(this));
  }

};

使用EnableShareFromThis的类

 struct A: EnableShareFromThis<A>{

      A(){cout << "A ctr....m" << endl;}
      ~A(){cout << "A dtr....m" << endl;}

      Shr_ptr<A> f()
      {
        return  SharedFromThis();
      }
    };

没有EnableShareFromThis的类

struct B{

  B(){cout << "B ctr...." << endl;}
  ~B(){cout << "B dtr...." << endl;}
};

测试用例

 void test()
    {
      //Check size of different objects, std enabled_from_this does not add extra size to A
      cout << "Size of A=" << sizeof(A) << " size of Shr_ptr=" << sizeof(Shr_ptr<A>) << " std::shr_ptr size=" << sizeof(shared_ptr<A>) << endl;

      Shr_ptr<A> p1(new A());
      cout << endl;

      cout << "{" << endl;
      {
        //Get SharedFromThis
        Shr_ptr<A> p5 = p1->f();
        Shr_ptr<A> p6 = p5->f();
        cout << "p5 use_count=" << p5.use_count() << ", p1 use_count=" << p1.use_count() << endl;
      }
      cout << "}" << endl;
      cout << endl;

      cout << "{" << endl;
      { 
        //Without SharedFromThis
        Shr_ptr<B> p7(new B());
        cout << "p7 use_count=" << p7.use_count() <<  endl;
      }
      cout << "}" << endl;
      cout << endl;

    }

    int main()
    {
      test();
      return 0;
    }