c ++如何在内部循环中使用带自动的向量擦除对象
c++ How to erase object using vector with auto while inside loop
大家好,Whosebug,
我一直想知道是否有任何简单的方法可以:迭代器控制的范围 for 循环 在访问容器时从容器中正确删除对象;使用自动它。
对于标准的索引控制 for 循环,我会这样做:
void del(int i){
cout<<"Deleting: "<<myObjects[i]<<':'<<myObjects[i]->c<<endl;
for(unsigned int j = 0; j < allObjects.size();){
if(allObjects[j] == myObjects[i]){
delete allObjects[j];
allObjects[j] = 0;
allObjects.erase(allObjects.begin()+j);
break;//Found and deleted first instance, escaping for-loop.
}else{
++j;
}
}
myObjects[i]=0;
myObjects.erase(myObjects.begin()+i);
}
自动 for 循环看起来像这样:
void del(int i){
cout<<myObjects[i]<<endl;
for(auto it: allObjects)
if(it == myObjects[i]){
delete it;
it = 0;
//allObjects.erase();// Found, needs erasing.
}
myObjects[i]=0;
myObjects.erase(myObjects.begin()+i);
}
我一直无法正确解决这个问题,一直在求助于老式索引(有很多方法可以使用索引)。
我可以删除它,并将其设置为 0,但是我如何在不知道索引的情况下将其从向量中删除,并且可能在向量中删除它?我知道我可以跟踪循环并使用计数器来这样做,但这会破坏使用干净的迭代器循环的目的。
如果不在向量中删除,除了重新访问向量之外,之后我将如何以一种简单的方式进行删除?
使用索引驱动的 for 循环没有错,只是想知道是否有使用我们的新朋友的简单替代方法 "auto it"。
谢谢。
抱歉,没有办法使用基于范围的for循环来擦除。您应该使用标准方式:
for(auto it = allObjects.begin(); it != allObjects.end();)
{
if(/* condition */)
it = allObjects.erase(it);
else
++it;
}
另请参阅此处的最佳答案:Can we erase the items in range-based for loop in c++11
您可以(并且应该)使用标准库,而不是滚动自己的循环:
allObjects.erase( std::remove(myObjects.begin(), myObjects.end, myObjects[i]),
allObjects.end() );
这样效率更高,因为您的算法是 O(n^2),因为元素一直在移动,而且更易读。
在你的例子中,因为你存储了指针,所以你必须先删除 "removed objects":
auto r = std::remove(myObjects.begin(), myObjects.end, myObjects[i]);
for(auto i=r; i != allObjects.end(); ++i) {
delete *i;
}
allObjects.erase(r, allObjects.end());
如果你使用智能指针(std:unique_ptr
或 std::shared_ptr
),这会更简单,因为你可以跳过手动循环,只使用普通的一行代码。
objects.erase(
std::remove_if(
objects.begin(),
objects.end(),
[](const Object &) -> bool {
// Do "some stuff", then return true if element should be removed.
return true;
}
),
objects.end()
);
您还可以使用 Boost.Range 和 Lambda。
大家好,Whosebug,
我一直想知道是否有任何简单的方法可以:迭代器控制的范围 for 循环 在访问容器时从容器中正确删除对象;使用自动它。
对于标准的索引控制 for 循环,我会这样做:
void del(int i){
cout<<"Deleting: "<<myObjects[i]<<':'<<myObjects[i]->c<<endl;
for(unsigned int j = 0; j < allObjects.size();){
if(allObjects[j] == myObjects[i]){
delete allObjects[j];
allObjects[j] = 0;
allObjects.erase(allObjects.begin()+j);
break;//Found and deleted first instance, escaping for-loop.
}else{
++j;
}
}
myObjects[i]=0;
myObjects.erase(myObjects.begin()+i);
}
自动 for 循环看起来像这样:
void del(int i){
cout<<myObjects[i]<<endl;
for(auto it: allObjects)
if(it == myObjects[i]){
delete it;
it = 0;
//allObjects.erase();// Found, needs erasing.
}
myObjects[i]=0;
myObjects.erase(myObjects.begin()+i);
}
我一直无法正确解决这个问题,一直在求助于老式索引(有很多方法可以使用索引)。
我可以删除它,并将其设置为 0,但是我如何在不知道索引的情况下将其从向量中删除,并且可能在向量中删除它?我知道我可以跟踪循环并使用计数器来这样做,但这会破坏使用干净的迭代器循环的目的。
如果不在向量中删除,除了重新访问向量之外,之后我将如何以一种简单的方式进行删除?
使用索引驱动的 for 循环没有错,只是想知道是否有使用我们的新朋友的简单替代方法 "auto it"。
谢谢。
抱歉,没有办法使用基于范围的for循环来擦除。您应该使用标准方式:
for(auto it = allObjects.begin(); it != allObjects.end();)
{
if(/* condition */)
it = allObjects.erase(it);
else
++it;
}
另请参阅此处的最佳答案:Can we erase the items in range-based for loop in c++11
您可以(并且应该)使用标准库,而不是滚动自己的循环:
allObjects.erase( std::remove(myObjects.begin(), myObjects.end, myObjects[i]),
allObjects.end() );
这样效率更高,因为您的算法是 O(n^2),因为元素一直在移动,而且更易读。
在你的例子中,因为你存储了指针,所以你必须先删除 "removed objects":
auto r = std::remove(myObjects.begin(), myObjects.end, myObjects[i]);
for(auto i=r; i != allObjects.end(); ++i) {
delete *i;
}
allObjects.erase(r, allObjects.end());
如果你使用智能指针(std:unique_ptr
或 std::shared_ptr
),这会更简单,因为你可以跳过手动循环,只使用普通的一行代码。
objects.erase(
std::remove_if(
objects.begin(),
objects.end(),
[](const Object &) -> bool {
// Do "some stuff", then return true if element should be removed.
return true;
}
),
objects.end()
);
您还可以使用 Boost.Range 和 Lambda。