2016-05-31 105 views
0

我最近阅读的一些帖子声称for(const auto &it : vec)与使用较长的迭代器语法for(std::vector<Type*>::const_iterator it = vec.begin(); it != vec.end(); it++)相同。但是,我遇到this post,说他们不一样。将const auto&转换为迭代器

目前,我试图擦除for循环中的一个元素,使用后,并想知道是否有任何方法将const auto &it : nodes转换为std::vector<txml::XMLElement*>::iterator

代码中的问题:

std::vector<txml2::XMLElement *> nodes; 
//... 
for (const auto &it : nodes) 
{ 
    //...  
    nodes.erase(it); 
} 

我敢肯定,我可以改写std::vector<txml2::XMLElement*>作为一个常量指针,但不会喜欢,因为这个代码仅仅是在当下调试。

回答

4

您不应该试图将基于循环的范围内的范围声明转换为迭代器,然后在迭代时删除它。即使在迭代时调整迭代器也很危险,而应该依赖算法。您应该使用Erase-remove idom
您可以使用remove_if

它看起来是这样的:

nodes.erase(std::remove_if(nodes.begin(), nodes.end(), [](auto it){ 

    //decide if the element should be deleted 
    return true || false; 

    }), nodes.end()); 

目前在技术规范,为erase_if
这是上面显示的相同的行为更清洁的版本:

std::erase_if(nodes,[](auto it){ 

    //decide if the element should be deleted 
    return true || false; 
}); 
+0

谢谢,这是一个巨大的帮助。最终使用'set_difference'结束了,但这让我走上了正确的道路。 – ZeroPhase

1

你没有得到一个迭代器,但该元素的引用。除非你想用它做一个std::find,否则很难得到一个迭代器。

向量很好,所以你可以增加一个计数器每个元素和做nodes.begin() + counter获得迭代器,但它有点击败点。

而且擦除迭代器会导致你的矢量结束后进行迭代的for循环,您可以测试这个代码:

#include <iostream> 
#include <vector> 

using namespace std; 

int main() { 
    vector<int> v = {0,1,2,3,4,5,6}; 

    for (int x : v) { 
     cout << x << endl; 

     if (x == 2) { 
      v.erase(v.begin() + 2); 
     } 
    } 
    return 0; 
} 

如果你想使用迭代器,只是做一个循环与他们如果除了要删除一个中循环,你必须遵循this answer

for (auto it = res.begin() ; it != res.end();) { 
    const auto &value = *it; 

    if (condition) { 
    it = res.erase(it); 
    } else { 
    ++it; 
    } 
} 

注意,你不需要指定整个类型的迭代器,auto作品一样好。