2016-05-31 13 views
0

Число сообщений, которые я читал в последнее время, for(const auto &it : vec) такое же, как с использованием более сильного синтаксиса итератора for(std::vector<Type*>::const_iterator it = vec.begin(); it != vec.end(); it++). Но я столкнулся с this post, который говорит, что они не то же самое.Преобразование const auto & to iterator

В настоящее время я пытаюсь стереть элемент в цикле 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, чтобы получить итератор, но это будет своего рода поражение.

Также удаление итератора в цикл приведет вас итерацию после конца вектора, вы можете проверить этот код:

#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 работает точно так же.