Как использовать «удаленные» элементы после std :: remove_if - PullRequest
2 голосов
/ 25 января 2009

Скажем, у нас есть:

struct IsEven {
   bool operator() (int i) { return i % 2 == 0; }
};

Тогда:

vector<int> V; // fill with ints
vector<int>::iterator new_end = remove_if(V.begin(), V.end(), IsEven());
V.erase(new_end, V.end());

работает нормально (оставляет V только с нечетными целыми числами). Но похоже, что элементы от new_end до V.end() являются , а не четными целыми числами, которые мы удаляем. Например, если v начинается как 1 4 2 8 5 7, тогда я получаю 8 5 7 для этих элементов (хотя после вызова erase вектор действительно имеет 1 5 7 слева).

По-видимому, (согласно http://www.sgi.com/tech/stl/remove_if.html)

The iterators in the range [new_last, last) are all still dereferenceable,
but the elements that they point to are unspecified.

Прежде всего, WTF? И во-вторых, как мне обойти это без существенного переопределения remove_if?

Ответы [ 3 ]

7 голосов
/ 25 января 2009

Звучит так, как будто вы хотите использовать partition() для разбиения вектора на группы нечетных значений в начале и четных значений в конце. partition() вернет итератор к первому элементу второй группировки.

Что касается WTF, я не уверен, почему вы ожидаете, что операция удаления сохранит элементы, которые вы хотите удалить, скопировав их (это дополнительная работа) в конец контейнера. Большинство людей считают WTF в remove() (и его двоюродных братьях) тем, что размер вектора не уменьшается, и вам нужно вызвать erase(), чтобы фактически удалить нежелательные элементы после операции удаления.

2 голосов
/ 25 января 2009

Если вы действительно хотите использовать «удаленные» элементы, вам нужно std :: partition .

2 голосов
/ 25 января 2009

Полагаю, дело в том, что функция вызывается remove_if по причине. Это удаляет элементы. Это не перемещает их или выбирает их. После того как вы вызвали remove_if, вы больше не гарантированы, что удаленные элементы существуют. Все, что вам гарантировано, это то, что элементы между first и new_last не содержат ни одного из удаленных элементов.

std::partition будет лучшим выбором, не так ли? Или, возможно, remove_copy_if, в зависимости от того, что именно вы пытаетесь сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...