如何从 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<holdable*>
对所有事物进行非拥有引用即可。
【参考方案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_iteratorAlf is correct,但出于某种对boost::ptr_vector
(以及其他相关的boost::reversible_ptr_container
容器)有些特殊的原因,我认为应该被调用。通常,容器元素的迭代器将取消对容器 value_type
的引用。
boost:ptr_vector<T>::value_type
是T*
的类型定义;但是,取消引用 boost::ptr_vector<T>::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<T>::iterator
会导致T&
。这就是为什么您对 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::any 的问题
boost::ptr_vector 与 std::vector<std::unique_ptr<T>>? [关闭]