首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否存在需要多个所有者的智能指针类型?

是否存在需要多个所有者的智能指针类型?
EN

Stack Overflow用户
提问于 2016-08-24 10:37:45
回答 3查看 386关注 0票数 9

当引用计数达到0时,std::shared_ptr会破坏它正在管理的对象。但是,我正在寻找一种智能指针,当引用计数降到2以下时,对象就会被销毁。是否有这样的智能指针(或者可以使智能指针以安全的方式运行)?

用例场景:我正在建模一个连接。连接由它所连接的两个端点所拥有(如“智能指针的所有权”中的那样)。一旦其中一个端点被破坏,连接也应该被销毁。

我知道我可以在适当的析构函数中使用经典的delete语句来实现这一点(因为在这种情况下,我对“低于2”的要求非常容易)。但我认为这是一种智能指针的有效用例,我很想看看我是否可以用一种现代的方式来做这件事。

EN

回答 3

Stack Overflow用户

发布于 2016-08-24 10:42:39

可能最简单的解决方案是,每一方都有一个指向对象的shared_ptr,一个指向对象的weak_ptr,以及一个指向另一端的shared_ptr的常规指针。

要访问该对象,请锁定weak_ptr。如果失败,对象就会消失。

要想摧毁自己,您可以锁定weak_ptr,通过指向它的常规指针重置对方的shared_ptr,重新设置您自己的shared_ptr,然后去掉weak_ptr锁的结果。

或者,您可以只使用计数器和常规指针。如果计数器是1,你知道另一边不见了,所以你可以直接销毁这个物体。

票数 4
EN

Stack Overflow用户

发布于 2016-08-27 00:28:45

谢谢你把你想要达到的效果包括在内。

您不需要或不需要智能指针中的任何特殊逻辑。两端都需要对共享对象的普通强引用。这清楚地表明,只要任何一方都知道它的存在,它就会生存。

相反,您需要的是一个事件通知,其中任何一方都可以在其离开时通知另一方。然后幸存的一方可以干净地进行适当的清理,包括将其(现在是最后一个) shared_ptr设置为null,但也可以执行逻辑上需要的任何其他操作。

票数 4
EN

Stack Overflow用户

发布于 2016-08-24 13:49:37

因为你有两个主人,当他们两个都死了,你想杀了它,我可能会这样做:

代码语言:javascript
复制
template<class T>
struct shared_connection {
  // by default, kill the connection if we are connected:
  ~shared_connection() {
    sever();
  }
  // wrap a shared pointer to the connection data:
  shared_connection( std::shared_ptr<T> p ):
    ptr(std::make_shared<std::shared_ptr<T>>(std::move(p)))
  {}
  // create a new connection:
  shared_connection fork() const {
    return {ptr};
  }
  // an even more explicit move:
  shared_connection transfer() {
    return std::move(*this);
  }
  friend void swap( shared_connection& lhs, shared_connection& rhs ) {
    std::swap( lhs.ptr, rhs.ptr );
  }
  // move only type:
  shared_connection(shared_connection&& src)
  {
    swap(*this, src);
  };
  shared_connection& operator=(shared_connection&& src)
  {
    auto tmp = std::move(src);
    swap(*this, tmp);
    return *this;
  };
  // lock it for use.  The connection can die
  // but the data will persist until the lock ends:
  std::shared_ptr<T> lock() const {
    if (!ptr) return {}; // don't break if we have been abandon()ed
    return atomic_load(ptr.get());
  }
  // do not kill the connection:
  void abandon() {
    ptr = {};
  }
  // kill the connection:
  void sever() {
    atomic_store(ptr.get(), std::shared_ptr<T>{});
    abandon();
  }
  // please just lock instead of calling this:
  explicit operator bool() const {
    return (bool)lock();
  }
private:
  std::shared_ptr<std::shared_ptr<T>> ptr;
};
template<class T, class...Args>
shared_connection<T> make_shared_connection( Args&&... args ) {
  return std::make_shared<T>(std::forward<Args>(args)...);
}

首先,通过一个shared_connection创建一个std::make_shared<T>

然后把它.fork()给另一方。当任何一个shared_connection都消失时,内部T就会被销毁,除非其中一个shared_connection已经对其进行了.lock()编辑。

我认为我的原子代码是正确的,所以它支持连接的两边处于不同的线程中。它还应该支持多党关系。

第一个共享指针表示连接解锁生存期的共享控件。第二个共享指针表示在短操作期间保持连接的能力。

.abandon()允许某人在不切断连接的情况下断开连接。.sever()允许您在不破坏对象的情况下销毁共享连接数据。

代码未被测试。

如果希望连接的每一方在共享连接结束时在一堆代码中共享所有权,则执行指向该共享连接的共享指针。因为没有什么能说爱就像共享指针指向共享指针一样。

我们还可以通过阻止应用程序中对它的访问来避免内部共享指针“泄漏”的可能性:

代码语言:javascript
复制
template<class F, class R=std::decay_t<std::result_of_t<F(T const&)>>>
std::optional<R> read( F&& f ) const {
  auto p = lock();
  if (!p) return {};
  T const& t = *p;
  return std::make_optional<R>( std::forward<F>(f)(t) );
}
template<class F, class R=std::decay_t<std::result_of_t<F(T&)>>>
std::optional<R> write( F&& f ) const {
  auto p = lock();
  if (!p) return {};
  T& t = *p;
  return std::make_optional<R>( std::forward<F>(f)(t) );
}

通过使用上述方法替换公共.lock()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39120972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档