Edd*_*223 91 c++ for-loop vector c++11
我有一个IInventory*的向量,我正在使用C++ 11范围循环遍历列表,以便对每个进行处理.
在做了一些东西之后,我可能想要从列表中删除它并删除对象.我知道我可以随时调用delete
指针来清理它,但是在范围for
循环中,从矢量中删除它的正确方法是什么?如果我从列表中删除它将使我的循环失效?
std::vector<IInventory*> inv;
inv.push_back(new Foo());
inv.push_back(new Bar());
for (IInventory* index : inv)
{
// Do some stuff
// OK, I decided I need to remove this object from 'inv'...
}
Run Code Online (Sandbox Code Playgroud)
Set*_*gie 84
不,你不能.基于范围for
是指您需要访问容器的每个元素一次.
for
如果需要随意修改容器,多次访问元素,或者以非线性方式遍历容器,则应使用普通循环或其中一个表兄弟.
例如:
auto i = std::begin(inv);
while (i != std::end(inv)) {
// Do some stuff
if (blah)
i = inv.erase(i);
else
++i;
}
Run Code Online (Sandbox Code Playgroud)
Bra*_*vic 53
每次从向量中移除元素时,必须假定擦除元素处于或之后的迭代器不再有效,因为移动了擦除元素之后的每个元素.
基于范围的for循环只是使用迭代器的"正常"循环的语法糖,因此上述情况适用.
话虽这么说,你可以简单地说:
inv.erase(
std::remove_if(
inv.begin(),
inv.end(),
[](IInventory* element) -> bool {
// Do "some stuff", then return true if element should be removed.
return true;
}
),
inv.end()
);
Run Code Online (Sandbox Code Playgroud)
dir*_*tly 14
理想情况下,迭代时不应修改向量.使用擦除删除习语.如果你这样做,你可能会遇到一些问题.由于在vector
一个erase
无效与元素开头的所有迭代器被擦除高达的end()
,你需要确保你的迭代器的使用仍然有效:
for (MyVector::iterator b = v.begin(); b != v.end();) {
if (foo) {
b = v.erase( b ); // reseat iterator to a valid value post-erase
else {
++b;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您需要按b != v.end()
原样进行测试.如果您尝试按如下方式对其进行优化:
for (MyVector::iterator b = v.begin(), e = v.end(); b != e;)
Run Code Online (Sandbox Code Playgroud)
因为你e
在第一次erase
通话后失效了,你会遇到UB .
在该循环中删除元素是否严格要求?否则,您可以将要删除的指针设置为NULL,并对向量进行另一次传递以删除所有NULL指针.
std::vector<IInventory*> inv;
inv.push_back( new Foo() );
inv.push_back( new Bar() );
for ( IInventory* &index : inv )
{
// do some stuff
// ok I decided I need to remove this object from inv...?
if (do_delete_index)
{
delete index;
index = NULL;
}
}
std::remove(inv.begin(), inv.end(), NULL);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
63329 次 |
最近记录: |