循环矢量时自动删除对象
我有一个对象的 std::vector ,我循环调用该对象的一些方法。其中之一将检查特定条件,如果需要,将从向量中删除其自身。关键是删除元素会使迭代器无效,并且我无法继续它的循环。我发现 boost::shared_ptr 和 boost::weak_ptr,这些可以解决在调用所有方法和递增迭代器后删除对象的问题吗?如果是这样,怎么办?
编辑1
class CPippo
{
public:
void Pippo();
void Pippo2();
}
class CPippoManager
{
public:
void PipppManager();
void RemovePippo(CPippo *pippo);
private:
std::vector<CPippo*> pippoVector;
}
void CPippo::Pippo()
{
...
if (condition)
{
pippoManager->RemovePippo(this);
}
}
void CPippo::Pippo2()
{
...
}
void CPippoManager::RemovePippo(CPippo *pippo)
{
this->pippoVector.erase(this->pippoVector.begin(), this->pippoVector.end(), pippo);
}
void CPippoManager::PipppManager()
{
for (std::vector<CPippo*>::iterator it = this->pippoVector.begin(); it != this->pippoVector.end; ++it)
{
(*it)->Pippo();
(*it)->Pippo2();
}
}
I have an std::vector of objects and i cycle it calling some methods of the object. One of them will check a particular condition and if needed will delete itsef from the vector. The point is that erasing the element invalidate the iterator and I cannot continue the loop of it. I found boost::shared_ptr and boost::weak_ptr, could these fix the problem deleting the object after calling all methods and after incremented the iterator? If so, how?
EDIT 1
class CPippo
{
public:
void Pippo();
void Pippo2();
}
class CPippoManager
{
public:
void PipppManager();
void RemovePippo(CPippo *pippo);
private:
std::vector<CPippo*> pippoVector;
}
void CPippo::Pippo()
{
...
if (condition)
{
pippoManager->RemovePippo(this);
}
}
void CPippo::Pippo2()
{
...
}
void CPippoManager::RemovePippo(CPippo *pippo)
{
this->pippoVector.erase(this->pippoVector.begin(), this->pippoVector.end(), pippo);
}
void CPippoManager::PipppManager()
{
for (std::vector<CPippo*>::iterator it = this->pippoVector.begin(); it != this->pippoVector.end; ++it)
{
(*it)->Pippo();
(*it)->Pippo2();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不要介意你的向量包含什么——托管资源的删除确实可以留给智能指针,但更紧迫的问题是如何操作容器本身。
std::vector
确实具有非常差的迭代器失效:擦除或插入会使从擦除/插入开始的所有迭代器失效,因此您甚至不能使用标准earase( it++)
习语。但你也不应该这样做,因为从向量中删除是昂贵的。更好的解决方案是使用删除/擦除并提供一个函子来检查擦除条件,然后一次性擦除所有内容:这里
MyPred
是一个实现您的标准的谓词。在 C++11 中,这可能是一个方便的 lambda。如果你现有的算法太复杂,也许你可以在自己的算法中采用
remove
的思想,用swap
将要擦除的对象移动到向量的后面>,并在算法结束时返回经过最后一个好元素的迭代器。然后,您可以在要删除的对象范围上拥有自己的可选清理循环,然后在该范围上调用erase
。Never mind what your vector contains - the deletion of managed resources can indeed be left to smart pointers, but the more pressing issue is how to manipulate the container itself.
std::vector
indeed has very poor iterator invalidation: erasing or inserting invalidates all iterators from the erasee/insertee onwards, so you cannot even use the standardearase(it++)
idiom. But neither should you, since erasing from a vector is expensive. The better solution is to use remove/erase and supply a functor that checks the condition for erasure, and then erase everything in one wash:Here
MyPred
is a predicate that implements your criterion. In C++11 this could be a handy lambda.If your existing algorithm is too involved, perhaps you can adapt the idea of
remove
in your own algorithm and move the to-be-erased object to the back of the vector withswap
, and return the iterator past the last good element at the end of the algorithm. Then you can have your own optional clean-up loop on the range of objects to be deleted, and then callerase
on that range.当您提到调用成员函数时,您应该使用
std erase/remove idiom ::mem_fun_ref
As you mention calling a member function you should the erase/remove idiom with
std::mem_fun_ref
要安全地从
向量
中删除元素,您应该使用erase-remove idiom< /a>.编辑:在我之前发布了很多好的回复,所以我想对
remove
添加一些额外的说明,因为它的运作方式并不是很明显。remove
算法实际上不会删除任何东西。它所做的只是对容器进行洗牌,以便所有要保留的元素都位于容器的开头。然后,它返回一个迭代器到保留元素的末尾(最后一个要保留的元素之后),此时您可以使用erase
来实际缩短容器。例如:向量 v;...
v.erase(remove(v.begin(), v.end(), 99), v.end());
将删除
v
中的所有元素值99。To safely delete elements from a
vector
you should use the erase-remove idiom.EDIT: Lots of good responses posted before mine, so thought I'd add a little extra clarification on
remove
because it's not immediately obvious how it operates. Theremove
algorithm doesn't actually remove anything. All it does is shuffle the container such that all the elements to keep are at the beginning of the container. It then returns an iterator to the end of the kept elements (one past the last element to keep) and that's when you useerase
to actually shorten the container. For example:vector v;...
v.erase(remove(v.begin(), v.end(), 99), v.end());
will remove all elements in
v
with the value 99.使用擦除-删除习惯用法:
这是一篇精彩的文章,讨论了编写涉及迭代器的算法的主题。
Use the erase-remove idiom:
This is a fantastic article talking about the subject of writing algorithms involving iterators.
您可以从erase() 返回一个有效的迭代器。
当然,您应该始终使用智能指针来管理资源。
You can get a valid iterator back from erase().
Of course, you should always use smart pointers to manage resources.