从列表中删除 boost::shared_ptr 的正确方法是什么?

发布于 2024-08-28 06:03:07 字数 1182 浏览 8 评论 0原文

我有一个 boost::shared_ptrstd::list ,我想从中删除一个项目,但我只有一个匹配的 T* 类型的指针列表中的项目之一。

但是我猜测我无法使用 myList.remove( tPtr ) 因为shared_ptr 没有为其模板参数类型实现 ==

我立即想到的是尝试 myList.remove(shared_ptr(tPtr) ) ,它在语法上是正确的,但它会因双重删除而崩溃,因为临时 shared_ptr 有一个单独的 use_count。

std::list< boost::shared_ptr<T> > myList;

T* tThisPtr = new T(); // This is wrong; only done for example code.
                       // stand-in for actual code in T using 
                       // T's actual "this" pointer from within T
{
   boost::shared_ptr<T> toAdd( tThisPtr ); // typically would be new T()
   myList.push_back( toAdd );
}

{
   //T has pointer to myList so that upon a certain action, 
   // it will remove itself romt the list

   //myList.remove( tThisPtr);                      //doesn't compile
   myList.remove( boost::shared_ptr<T>(tThisPtr) ); // compiles, but causes
                                                    // double delete
}  

我看到剩下的唯一选择是使用 std::find 进行自定义比较,或者循环遍历列表并自己找到它,但似乎应该有更好的方法。

我是否遗漏了一些明显的东西,或者这是否太不标准,无法以干净/正常的方式进行删除?

I have a std::list of boost::shared_ptr<T> and I want to remove an item from it but I only have a pointer of type T* which matches one of the items in the list.

However I cant use myList.remove( tPtr ) I'm guessing because shared_ptr does not implement == for its template argument type.

My immediate thought was to try myList.remove( shared_ptr<T>(tPtr) ) which is syntactically correct but it will crash from a double delete since the temporary shared_ptr has a separate use_count.

std::list< boost::shared_ptr<T> > myList;

T* tThisPtr = new T(); // This is wrong; only done for example code.
                       // stand-in for actual code in T using 
                       // T's actual "this" pointer from within T
{
   boost::shared_ptr<T> toAdd( tThisPtr ); // typically would be new T()
   myList.push_back( toAdd );
}

{
   //T has pointer to myList so that upon a certain action, 
   // it will remove itself romt the list

   //myList.remove( tThisPtr);                      //doesn't compile
   myList.remove( boost::shared_ptr<T>(tThisPtr) ); // compiles, but causes
                                                    // double delete
}  

The only options I see remaining are to use std::find with a custom compare, or to loop through the list brute force and find it myself, but it seems there should be a better way.

Am I missing something obvious, or is this just too non-standard a use to be doing a remove the clean/normal way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

画骨成沙 2024-09-04 06:03:07

你是对的,我们不能直接比较指针。但确实存在remove_if,我们可以指定自己的谓词。解决方案:

template <typename T>
struct ptr_contains_predicate
{
    ptr_contains_predicate(T* pPtr) :
    mPtr(pPtr)
    {}

    template <typename P>
    bool operator()(const p& pPtr) const
    {
        return pPtr.get() == mPtr;
    }

    T* mPtr;
};

template <typename T>
ptr_contains_predicate<T> ptr_contains(T* pPtr)
{
    return ptr_contains_predicate<T>(pPtr);
}

只需将上述谓词保留在标头中的某个位置,您就可以在任何您想要的地方使用它。

myList.remove_if(ptr_contains(tThisPtr));

最好的解决方案是从一开始就永远不要失去对 shared_ptr 的控制,因此我们可以只使用 remove,但以上方法无论如何都是无害的。

You're correct, we can't directly compare the pointers. But there does exist remove_if, and we can specify our own predicate. The solution:

template <typename T>
struct ptr_contains_predicate
{
    ptr_contains_predicate(T* pPtr) :
    mPtr(pPtr)
    {}

    template <typename P>
    bool operator()(const p& pPtr) const
    {
        return pPtr.get() == mPtr;
    }

    T* mPtr;
};

template <typename T>
ptr_contains_predicate<T> ptr_contains(T* pPtr)
{
    return ptr_contains_predicate<T>(pPtr);
}

Just keep the above predicate in a header somewhere, and you can use it wherever you want.

myList.remove_if(ptr_contains(tThisPtr));

The best solution is to never lose hold of the shared_ptr in the first place, so we can just use remove, but the above is harmless anyway.

§对你不离不弃 2024-09-04 06:03:07

std::list 的 remove_if 成员就是您所需要的:

定义一个谓词

template <typename T> struct shared_equals_raw
{
  shared_equals_raw(T* raw)
    :_raw(raw)
    {}
  bool operator()(const boost::shared_ptr<T>& ptr) const
    {
      return (ptr.get()==_raw);
    }
private:
  T*const _raw;
};

然后 您可以调用

myList.remove_if(shared_equals_raw(tThisPtr));

列表来清理具有shared_ptrs到tThisPtr的节点。

(未经测试,所以也许一些语法问题需要修复)。

Michael Burr关于enable_shared_from_this的建议很好;最好完全避免使用原始 tThisPtr。

std::list's remove_if member is what you need:

Define a predicate

template <typename T> struct shared_equals_raw
{
  shared_equals_raw(T* raw)
    :_raw(raw)
    {}
  bool operator()(const boost::shared_ptr<T>& ptr) const
    {
      return (ptr.get()==_raw);
    }
private:
  T*const _raw;
};

then you can call

myList.remove_if(shared_equals_raw(tThisPtr));

to have the list clean up nodes which have shared_ptrs to tThisPtr.

(Untested, so maybe some syntactic stuff needs fixing).

Michael Burr's advice re enable_shared_from_this is good though; it'd be better to avoid having the raw tThisPtr in play at all.

梦幻的味道 2024-09-04 06:03:07

enable_shared_from_this 可以帮助解决您的问题,但它需要您在列表中使用的类型派生自它:

如果类型启用功能,您可以通过调用 shared_from_this() 从对象本身获取共享指针。

enable_shared_from_this can help with your problem, but it will require that the types you're using in the list derive from it:

If the type enables that functionality, you can get the shared pointer from the object itself by calling shared_from_this().

格子衫的從容 2024-09-04 06:03:07

可以使用共享指针来删除它吗?

std::list< boost::shared_ptr<T> > myList;

boost::shared_ptr<T> tThisPtr = new T(); 

{
    myList.push_back(tThisPtr);
}

{
    myList.remove(tThisPtr);                     
}

Can you use the shared pointer to remove it?

std::list< boost::shared_ptr<T> > myList;

boost::shared_ptr<T> tThisPtr = new T(); 

{
    myList.push_back(tThisPtr);
}

{
    myList.remove(tThisPtr);                     
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文