Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::共享\u ptr自定义参考计数器_C++_Shared Ptr - Fatal编程技术网

C++ std::共享\u ptr自定义参考计数器

C++ std::共享\u ptr自定义参考计数器,c++,shared-ptr,C++,Shared Ptr,我目前正在编写一段代码,需要在代码的多个部分之间静态共享对象的实例。所以基本上是单身。此实例将被共享,直到没有人再使用它为止。此时,我需要在删除实际实例之前执行一些清理操作 如果有人在此之后请求共享实例,它将得到一个新创建的实例,依此类推 所以我写了这样的东西: template<typename F> struct static_filter { template<typename ...Args> static std::shared_ptr<F>

我目前正在编写一段代码,需要在代码的多个部分之间静态共享对象的实例。所以基本上是单身。此实例将被共享,直到没有人再使用它为止。此时,我需要在删除实际实例之前执行一些清理操作

如果有人在此之后请求共享实例,它将得到一个新创建的实例,依此类推

所以我写了这样的东西:

template<typename F>
struct static_filter
{
  template<typename ...Args>
  static std::shared_ptr<F> get(Args... a)
  {
    return _inst = _inst ?: std::shared_ptr<F>(new F(a...));
  }

  static void cleanup()
  {
    // some cleanup operation over inst
    _inst.reset();
  }

private:
  static std::shared_ptr<F> _inst;
};

template<typename F> std::shared_ptr<F> static_filter<F>::_inst{nullptr};
模板
结构静态过滤器
{
样板
静态std::shared_ptr get(Args…a)
{
return _inst=_inst?:std::shared_ptr(新F(a…);
}
静态空洞清理()
{
//inst上的一些清理操作
_仪器复位();
}
私人:
静态标准::共享ptr仪器;
};
模板std::shared_ptr static_filter::_inst{nullptr};
现在,我正在寻找一种自动检测何时没有人再使用inst的方法。 基本上,每次_inst的use_count()降到1时,我都希望得到一个回调。在这一点上,我将能够清理和重置

我希望避免为此实现我自己的引用计数(应用程序在任何地方都使用shared_ptr,并且更改为自定义类型会有点烦人)

我尝试在我的实例上使用自定义删除程序,大致如下:

template<typename F>
struct static_filter
{
  template<typename ...Args>
  static std::shared_ptr<F> get(Args... a)
  {
    return _inst = _inst ?: std::shared_ptr<F>(new F(a..., **static_filter<F>::cleanup**));
  }

  static void cleanup()
  {
    // some cleanup operation over inst
    _inst.reset();
  }

private:
  static std::shared_ptr<F> _inst;
};

template<typename F> std::shared_ptr<F> static_filter<F>::_inst{nullptr};
模板
结构静态过滤器
{
样板
静态std::shared_ptr get(Args…a)
{
return _inst=_inst?:std::shared_ptr(新F(a…,**静态_过滤器::清理**);
}
静态空洞清理()
{
//inst上的一些清理操作
_仪器复位();
}
私人:
静态标准::共享ptr仪器;
};
模板std::shared_ptr static_filter::_inst{nullptr};
但很明显,这不起作用,因为我的ref计数器从未真正达到0

有人知道是否有一种方法可以通过共享ptr实现这一点吗


谢谢。

您在这里使用的
共享\u ptr
在语义层面上是错误的。您不希望持有此
静态
变量的所有权,而只希望通过它进行观察。这是的用例。使用此静态变量,您可以观察对象,将其作为
shared_ptr
返回(如果存在),并且在其他人持有对其的引用时,不干涉其销毁

这将如下所示:

模板
结构静态过滤器
{
样板
静态std::shared_ptr get(Args…a)
{
//返回观察到的共享ptr,如果它存在且未过期,则清空ptr,否则为空
//是原子的
自动共享=_inst.lock();
如果(!共享){
_inst=(shared=std::shared_ptr(新F(a…,**静态_过滤器::清理**));
}
收益共享;
}
静态空洞清理()
{
//始终检查调用对象是否确实是托管对象
//inst上的一些清理操作
_仪器复位();
}
私人:
静态标准:弱ptr仪器;
};
模板std::弱\u ptr静态\u过滤器::\u inst{};
请注意,这不是线程安全的(您以前的代码也不是线程安全的),因为当指针为空时,同时调用两个
get
,都可以看到指针为空,并且都可以构造类型为
F
的新对象。您必须添加
std::lock\u-guard
以避免这种情况


请注意,即使您可以在
use\u count==1
上添加回调,这本身就是不安全的。这就是为什么
std::shared\u ptr::unique()
从C++17开始被弃用,并在C++20中被删除的原因(请参阅和)

我意识到这一点,我正在寻找一种在实际值达到1时得到通知的方法。这里的目标是不必手动调用cleanup(),而是在代码的其他部分没有对_inst.Make
\u inst
的引用时立即触发它。
get()
执行一个
\u inst.lock()
并且如果锁失败,那么它会创建一个新的。F的析构函数就是你的
清理
。这正是我想要的。你说的对,我在这里使用共享的\u ptr是无效的。非常感谢你的帮助:)