为什么enable_shared_from_this不能直接访问内嵌的weak_ptr ?

Why does enable_shared_from_this lack direct access to the embedded weak_ptr?

本文关键字:ptr 访问 weak shared enable from this 为什么 不能      更新时间:2023-10-16

我想在多线程应用程序中使用boost signals2与自动连接管理。我的类继承自enable_shared_from_this<>,我想从另一个成员方法中连接一个成员方法。连接可能会频繁重建,所以我的代码应该尽可能快(尽管从boost signals2性能本身):

typedef boost::signals2::signal<void ()> signal_type;
struct Cat : public enable_shared_from_this<Cat>
{
  void meow ();
  void connect (signal_type& s)
  {
    // can't write this
    s.connect (signal_type::slot_type (&Cat::meow, this, _1).track (weak_from_this ()));
    // ok, but slow?! two temporary smart pointers
    weak_ptr<Cat> const myself (shared_from_this ());
    s.connect (signal_type::slot_type (&Cat::meow, this, _1).track (myself));
  }
  // i am missing something like this in the base class
  // protected:
  //   weak_ptr<Cat> const& weak_from_this ();
};

我知道我的设计目标可能是冲突的(自动连接管理和线程安全,以及快速代码),但无论如何:

  1. 为什么enable_shared_from_this<>不能直接访问嵌入式weak_ptr<> ?我找不出反对的理由。是否没有类似于我的用例?

  2. 是否有比上面更快的解决方案?

编辑:

我知道我可以这样做,但我想避免额外的存储/初始化检查的惩罚:

template <typename T>
struct enable_weak_from_this : public enable_shared_from_this<T>
{
protected:
  weak_ptr<T> /* const& */ weak_from_this ()
  {
    if (mWeakFromThis.expired ())
    {
      mWeakFromThis = this->shared_from_this ();
    }
    return mWeakFromThis;
  }
private:
  weak_ptr<T> mWeakFromThis;
};

您不能访问weak_ptr的原因是enable_shared_from_this必须使用一个。拥有weak_ptr只是enable_shared_from_this的一个可能的实现。它不是唯一的。

由于enable_shared_from_this是与shared_ptr相同的标准库的一部分,因此可以使用比直接存储weak_ptr更有效的实现。委员会不想阻止这种优化。

//好,但是慢吗?两个临时智能指针

这只是一个临时智能指针。除了第一个对象,复制省略/移动应该照顾到其他对象。

这可能是因为没有shared_ptr引用Cat实例。weak_ptr要求至少有一个活动shared_ptr

尝试将shared_ptr作为成员变量并首先在connect方法中分配给它:

typedef boost::signals2::signal<void ()> signal_type;
struct Cat : public enable_shared_from_this<Cat>
{
  void meow ();
  boost::shared_ptr<Cat> test;
  void connect (signal_type& s)
  {
    test = shared_from_this();
    s.connect (signal_type::slot_type (&Cat::meow, this, _1).track (weak_from_this ()));
  }
};

但基本上,如果没有shared_ptr,就没有weak_ptr。如果所有的shared_ptr都消失了,而weak_ptr还在使用中,那么weak_ptr可能指向一个不存在的对象。

注意:我的测试不应该在生产代码中使用,因为它将导致对象永远不会被释放。