Удалить неправильно
std::vector<int> v = {1,2,3,4,5};
auto i = std::remove(v.begin(),v.end(),3);
for(auto j = v.begin(); j!= v.end();++j)
std::cout << *j;
Фактический выход: 12455
Откуда берутся дополнительные 5?
Требуемый вывод: 1245
Как добиться того же?
Я действительно хочу, чтобы размер вектора менялся, ответ, данный Prasoon saurav выглядит корректно
Ответы
Ответ 1
remove
фактически не удаляет элементы
Удалить удаляет из диапазона [first, last)
все элементы, которые равны value
. То есть remove возвращает итератор new_last
, так что диапазон [first, new_last)
не содержит элементов, равных value
. 1 Итераторы в диапазоне [new_last, last)
все все еще разыскиваются, но элементы, на которые они указывают, являются неопределенные. Удалить является стабильным, что означает, что относительный порядок элементов, которые не равны значению, не изменяется. `
std::remove
алгоритм работает только с использованием пары передовых итераторов и вообще ничего не знает о базовом контейнере.
Вам нужно использовать erase-remove
idiom для на самом деле удалить элемент, т.е. объединить erase
с remove
auto i = std::remove(v.begin(),v.end(),3);
v.erase(i,v.end());
for(auto j = v.begin(); j!= v.end();++j)
std::cout << *j;
Ответ 2
Снова прочитайте документацию для std::remove
.
Функция не удаляет элементы из контейнера (фактически, он даже не знает, что задействован контейнер, поскольку он видит только итераторы), он просто перемещает значения в последовательности и возвращает новый итератор i
так что весь интервал [ begin .. i [
содержит все неиспользуемые элементы в исходном порядке. Элементы, оставшиеся в [ i .. end [
, не указаны, и вы несете ответственность за удаление этого интервала из контейнера (если вам это нужно):
auto i = std::remove(...);
v.erase(i,v.end());
Причина, по которой у вас есть дополнительный 5
, заключается в том, что типичный алгоритм удаления копирует значения в отверстия, оставшиеся от удаленных значений, и поскольку значения, прошедшие после итератора i
, никогда не перезаписываются, они остаются такими же, как в исходной последовательности, Однако это поведение не является надежным - просто удалите значения i
без их чтения.
Ответ 3
remove
возвращает новый конец. Итак, исправление вашего кода таково:
std::vector<int> v = {1,2,3,4,5};
auto newEnd = std::remove(v.begin(),v.end(),3);//return value stored in newEnd
for(auto j = v.begin(); j!= newEnd ;++j) //note j!=newEnd
std::cout << *j;
Вывод:
1245
Проверьте сами: http://www.ideone.com/3AMD9
Ответ 4
Это означает, что вы печатаете позицию n + 1 вектора в инструкции for()
.
Это должно быть:
for(auto j = v.begin(); j!= v.end();j++)
std::cout << *j;
j++
no ++j