Неверный код удаления. Удалить стирание идиомы выглядит следующим образом:
vector<int>::iterator it = remove(v.begin(), v.end(), 5);
v.erase(it, v.end());
В этом случае он имеет эффект стирания всех значений, равных 5, но это сводит к минимуму количество копирования, необходимое для достижения этой цели.
Ваш код удаления удаляет только первое значение, равное 5, поэтому он делает то, что вы хотите.
Код удаления удаляет все значения, не равные 5, перед вектором (это то, что делает std::remove
), удаляет один из оставшихся элементов вектора и оставляет после себя оставшиеся элементы с неопределенными значениями (что также является то, что делает remove
). Он имеет неопределенное поведение, если вектор не содержит 5
для начала, потому что remove
вернет v.end()
в этом случае.
Итак, если вы хотите стереть только один элемент из нескольких равных 5, то std::remove
вам не подходит, потому что он не сохраняет 5 других.Если вы хотите, чтобы переместить не-5 значений в начале и 5 значений до конца, перед удалением первого из 5s, то вы могли бы на самом деле сделать это с std::partition
просто не с std::remove
:
auto it = partition(v.begin(), v.end(), [](int i) { return i != 5; });
if (it != v.end()) v.erase(it);
Хотя, так как один-так же хорошо, как и другие, вы получите тот же результат, удалив последние из 5s, а не первый, и это более эффективно, когда есть более чем один из них:
auto it = partition(v.begin(), v.end(), [](int i) { return i != 5; });
if (it != v.end()) v.pop_back();
Если вы можете как-то убедитесь, что вектор изначально содержит ровно один элемент, равный 5 (не более или более s), то ваши два бита кода делают то же самое. И в этом случае вам не нужен тест для it != v.end()
в коде поиска-стирания, вы бы знали, что он не равен. Вы могли бы просто сделать v.erase(find(v.begin(), v.end(), 5))
.
[Я сделал здесь два комментария, но они оба были неправы, пожалуйста, игнорируйте :-)] –
Здесь лучше ответить: https://stackoverflow.com/questions/24011627/erasing-using-iterator-from- find-or-remove – giuseppe