如何从 boost::ptr_vector 中删除“this”

Posted

技术标签:

【中文标题】如何从 boost::ptr_vector 中删除“this”【英文标题】:How to erase "this" from boost::ptr_vector 【发布时间】:2012-11-11 03:24:07 【问题描述】:

我有一个 boost::ptr_vector 包含指向“可持有”类的指针。

boost::ptr_vector<holdable> items;

我从可持有类中向该向量添加新项目,如下所示:

currentplanet->items.push_back(this);

其中 currentplanet 是指向包含 ptr_vector 的类的对象的指针。这一切都很好。

我感到困惑的是如何从 ptr_vector 中从它自己的类中的函数中删除一个条目。我正在尝试:

currentplanet->items.erase(std::find(currentplanet->items.begin(),
                                     currentplanet->items.end(),
                                     this));

根据此处类似问题的答案:How to erase elements from boost::ptr_vector,但我显然在某个地方出错了,可能与“this”的使用有关。

在尝试编译时,我收到来自 stl_algo.h 的错误提示

stl_algo.h|174|error: no match for 'operator==' in '__first.boost::void_ptr_iterator<VoidIter, T>::operator*
  [with VoidIter = __gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, 
  T = holdable]() == __val'|

我确定这很明显,但我可能对 ptr_vector 的间接性感到困惑......提前感谢您的任何回答!

【问题讨论】:

你的设计无论如何都是有缺陷的,我认为。 ptr_vector 拥有其中的指针。如果您已经有一个this,则 else 拥有该对象。将其添加到ptr_vector 是没有意义的。只需使用 std::vector&lt;holdable*&gt; 对所有事物进行非拥有引用即可。 【参考方案1】:

正如其他人所写 - ptr_vector 确实拥有您的对象的所有权,但如果您坚持能够自行从 ptr_vector 中删除对象 - 使用 find_if,而不是 find:

Holdable* ptr = this;
currentplanet->items.erase(std::find_if(currentplanet->items.begin(),
                                        currentplanet->items.end(),
                                        [ptr](const Holdable& other) 
                                        return ptr == &other; ));

注意find*this 一起使用可能会找到其他等于*this 的对象...


对于仍然不支持 lambda 表达式的编译器(这个东西从 [ptr] 开始),使用你自己的谓词:

struct CompareToPtr  
    CompareToPtr(Holdable* ptr) : ptr(ptr) 
    bool operator () (const Holdable& other) const  return &other == ptr; 
    Holdable* ptr;
;
currentplanet->items.erase(std::find_if(currentplanet->items.begin(),
                                        currentplanet->items.end(),
                                        CompareToPtr(this)));

【讨论】:

谢谢,但我担心这会抛出一个 holdable.h|48|error: expected primary-expression before '[' token| (其中第 48 行以上述 sn-p 中的 [ptr] 开头)。我错过了什么明显的东西吗? @Riot:PiotrNycz 的代码 sn-p 使用您的编译器可能不支持的 C++11 lambda 表达式(或者可能需要指定一个选项来启用这种支持)。如果 C++11 不适合您,您可以将 find_if() 谓词参数(lambda 的用途)设为仿函数,甚至是普通的旧函数。【参考方案2】:

我知道 std::find 需要第三个参数的值(不是指针),所以你传递了一个 ["begin", "end") 范围来寻找,以及你寻找的值

这是你的意思吗?

currentplanet->items.erase(std::find(currentplanet->items.begin(),
                                     currentplanet->items.end(),
                                     *this));

注意 *this

【讨论】:

ptr_vector 中的其他对象可能等于*this - 所以不一定会返回this 对象迭代器。 恐怕这是我尝试的第一件事 - 这似乎不是有效的代码。编译器说: stl_algo.h|174|error: no match for 'operator==' in '__first.boost::void_ptr_iterator::operator* [with VoidIter = __gnu_cxx::__normal_iterator >>, T = holdable]() == __val'|【参考方案3】:

Alf is correct,但出于某种对boost::ptr_vector(以及其他相关的boost::reversible_ptr_container 容器)有些特殊的原因,我认为应该被调用。通常,容器元素的迭代器将取消对容器 value_type 的引用。

boost:ptr_vector&lt;T&gt;::value_typeT* 的类型定义;但是,取消引用 boost::ptr_vector&lt;T&gt;::iterator 不会产生 T* 引用。

来自 Boost 文档 (http://www.boost.org/doc/libs/1_52_0/libs/ptr_container/doc/reversible_ptr_container.html):

还要注意

typedef ... iterator

允许遍历 T& 对象,而不是 T*。

取消引用boost::ptr_vector&lt;T&gt;::iterator 会导致T&amp;。这就是为什么您对 ptr_vector 的间接性感到困惑,这就是为什么 std::find() 的最后一个参数需要是 holdable 对象而不是 holdable*

最后,请注意 Xeo 关于 ptr_vector 获取指针所有权的评论应该被理解 - 在非常有限的情况下,对象想要删除自己可能是有意义的,但您应该在充分理解的情况下这样做在那次erase() 电话之后,你不能再对这个对象做任何事情了。如果这不是您需要的行为,那么您可能需要考虑使用release() 而不是erase(),这将释放容器对指针的所有权并将其从容器中删除(因此对象不会被破坏)。

【讨论】:

谢谢,但正如我在 Alf 的回复中评论的那样,使用“*this”会产生编译器错误。有什么办法可以让我知道吗?顺便说一下,澄清一下——这确实是在对象要删除自身的情况下。 我认为此时的问题是您没有允许比较 holdable 对象的 operator==()。您可能想发布一个小而完整的示例,让编译器显示您看到的错误(该示例可能需要class holdable,但您可能不需要currentplanet 对象就可以逃脱)。 但是,您应该注意 PiotrNycz 的回答 - 您肯定需要处理比较相同的 holdable 对象的问题 - 通过使用他的 find_if() 解决方案使用对象地址或通过不允许在items 中的对象中发生这种情况(这可能是处理问题的一种相当脆弱的方法)。

以上是关于如何从 boost::ptr_vector 中删除“this”的主要内容,如果未能解决你的问题,请参考以下文章

boost::ptr_vector 的引用或指针表示法

boost::ptr_vector 和 boost::any 的问题

boost::ptr_vector 与 std::vector<std::unique_ptr<T>>? [关闭]

如何从 git bash 屏幕中删除文件并从存储库中删除该文件? [复制]

从库中删除文件后如何从 Xcode 中删除引用?

如何从反应项目中删除故事书