C++ 2a

std::enable_shared_from_this的用法

2022-06-22  本文已影响0人  左图右码

有些类的成员函数需要获得自身的std::shared_ptr,但不能就地从this创建,这样会导致多个毫无关系的智能指针引用到同一个对象,导致重复释放【不能传递share_ptr<this>,因为这样会造成2个以上非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次】。
std::enable_shared_from_this<>模版类就是解决这个问题。
请看regTo的实现,就需要使用本身的智能指针。

class base : public std::enable_shared_from_this<base>
{
    std::string msg;
public:
    base(std::string s) : msg(s){}
    virtual ~base() = default;
    virtual void print()
    {
        std::cout << msg << std::endl;
    }
    void regTo(class regObj*);
};

class regObj
{
    std::vector<std::shared_ptr<base>> objs;
public:
    void regobject(std::shared_ptr<base> shp)
    {
        objs.push_back(shp);
    }
    void print()
    {
        for (auto& c : objs)
            c->print();
    }
};

void base::regTo(class regObj* p)
{
    p->regobject(this->shared_from_this());
}

class concrete1 : public base
{
public:
    concrete1(const char* msg) : base(msg){}
};

class concrete2 : public base
{
public:
    concrete2(const char* msg) : base(msg) {}
};


int main(int,const char**)
{
    auto instance = new regObj;
    auto p1 = std::make_shared<concrete1>("concreteObj1");
    std::shared_ptr<concreate2> p2(new concrete2("concreteObj2"));
    p1->regTo(instance);
    p2->regTo(instance);
    instance->print();
    delete instance;
}

上面regTo函数就需要获得本身的shared_ptr。
注意:调用这个函数的实例必须是构建在shared_ptr上的。因为shared_from_this是从一个weak_ptr构建的一个shared_ptr,这里的weak_ptr是一个shared_ptr弱引用。如果本身没有构建,自然弱引用也是空的。

如果如下所示的使用,则会发生运行时错误:

auto ptr = new concrete2("concreteObj3");
ptr->regTo(instance);

抛出异常的位置在这里:

    template<class _Ty2,
    enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
    explicit shared_ptr(const weak_ptr<_Ty2>& _Other)
    {   // construct shared_ptr object that owns resource *_Other
      if (!this->_Construct_from_weak(_Other))
        {
          _THROW(bad_weak_ptr{});
        }
    }
上一篇下一篇

猜你喜欢

热点阅读