2011-01-10 2 views
49

У меня есть этот код:вектора Стирание итератор

int main() 
{ 
    vector<int> res; 
    res.push_back(1); 
    vector<int>::iterator it = res.begin(); 
    for(; it != res.end(); it++) 
    { 
     it = res.erase(it); 
     //if(it == res.end()) 
     // return 0; 
    } 
} 

«итератор произвольного доступа, указывающий на новое местоположение элемента, а затем последний элемент стерт при вызове функции, которая является вектор конца, если операции стереть последний элемент в последовательности ".

Этот код вылетает, но если я использую if (it == res.end()), а затем возвращает его. Как так? Задает ли цикл for сообщение res.end(), поэтому оператор, не равный нулю, не работает?

+1

Почему бы не использовать 'res.clear()'? – Benoit

+0

Аналогичный вопрос: http://stackoverflow.com/questions/347441/erasing-elements-from-a-vector – Naveen

+6

, потому что это просто упрощение кода, я не пытаюсь удалить все элементы в реальном коде – hidayat

ответ

110

res.erase(it) всегда возвращает следующий действительный итератор, если вы удалите последний элемент будет указывать на .end()

В конце цикла ++it всегда называется, так что вы увеличиваете .end(), не допускаются.

Просто проверка .end() по-прежнему оставляет ошибку, хотя, как вы всегда пропустить элемент на каждой итерации (it получает «приращение» по возвращению из .erase(), а затем снова петли)

Вы, вероятно, хотите что-то как:

while (it != res.end()) { 
     it = res.erase(it);  
} 

удалить каждый элемент

(для полноты: Я полагаю, что это упрощенный пример, если вы просто хотите, каждый элемент ушел без Havi ng для выполнения операции над ним (например, удаление), следует просто вызвать res.clear())

Когда вы только условно удалить элементы, вы, вероятно, хотите что-то вроде

for (; it != res.end();) { 
    if (condition) { 
    it = res.erase(it); 
    } else { 
    ++it; 
    } 
} 
+0

ok, поэтому он сначала увеличивает и после инкремента сравнивает – hidayat

+0

Нет, hidayat; ваш код пытается удалить все элементы в векторе по одному. Для этого вы должны начать с 'res.begin()', а затем никогда не продвигать итератор, но извлекать итератор, возвращаемый при стирании элемента (то же самое касается всех контейнеров STL). Сам прирост - это часть, которая неправильна. – Mephane

+0

в реальном коде я не пытаюсь удалить все элементы, но спасибо, я понимаю, что я сделал неправильно сейчас – hidayat

0

Не стирать, а затем увеличивать итератор. Нет необходимости увеличивать, если у вашего вектора есть странное (или даже не знаю) количество элементов, которые вы пропустите в конце вектора.

0

Инструкция it ++ выполняется в конце блока. Поэтому, если вы удаляете последний элемент, вы пытаетесь увеличить итератор, указывающий на пустую коллекцию.

0

Вы увеличиваете it в конце (пустой) контейнера в выражении цикла цикла цикла.

25
for(; it != res.end();) 
{ 
    it = res.erase(it); 
} 

или, более общий:

for(; it != res.end();) 
{ 
    if (smth) 
     it = res.erase(it); 
    else 
     ++it; 
} 
+0

Ваша задача, потому что она отлично работала для меня^_^ – espais

+0

Почему бы не использовать 'while'? – chamini2

0

также следующее, кажется, работает:

for (vector<int>::iterator it = res.begin(); it != res.end(); it++) 
{ 
    res.erase(it--); 
} 

Не уверен, что если есть какая-либо ошибка в этом?

+0

Хотя этот код может ответить на вопрос, лучше объяснить, что он делает, и добавить некоторые ссылки на него. – dotctor

+1

Я не уверен в коде выше. Есть три основные проблемы, которые я вижу. Во-первых, вы не возвращаете res.erase (it) обратно в 'it' после удаления. Вы не должны иметь его внутри внутри оператора iterator при удалении вещей, поэтому вы должны иметь условную проверку, чтобы удалить его. Если условие терпит неудачу, вы выполните итерацию до следующего ('it ++'). Хотя мне интересно, почему у вас есть это? Простите меня, но почему вы даже уменьшаете итератор? Может быть, я споткнулся, если это так, я извиняюсь. –

+0

@VG Спасибо, я думаю, ваш комментарий затрагивает вопрос в ответе, поэтому делает его учебным и, возможно, стоит упомянуть. Боюсь, я еще не понимаю логику «этого», слишком много воды течет под мостом с тех пор ... –

0
if(allPlayers.empty() == false) { 
    for(int i = allPlayers.size() - 1; i >= 0; i--) 
    { 
     if(allPlayers.at(i).getpMoney() <= 0) 
      allPlayers.erase(allPlayers.at(i)); 
    } 
} 

Это работает для меня. И не нужно думать, что индексы уже стерты.

+0

Как вы можете это сказать работает для вас? Вы никогда не проверяли это. Это даже не компилируется. alllPlayers.at (i) не возвращает итератор. Но erase() ожидает итератор. – Elmue

1

В качестве модификации к ответу crazylammer, я часто использую:

your_vector_type::iterator it; 
for(it = res.start(); it != res.end();) 
{ 
    your_vector_type::iterator curr = it++; 
    if (something) 
     res.erase(curr); 
} 

Преимущество этого в том, что вам не придется беспокоиться о забывая увеличивать свой итератор, что делает его менее ошибка склонными когда у вас есть сложная логика. Внутри цикла, curr никогда не будет равен res.end(), и он будет в следующем элементе независимо от того, удалите ли вы его из вашего вектора.

Смежные вопросы