Как передать параметр «const_reverse_iterator» в «std :: vector :: erase ()»? - PullRequest
2 голосов
/ 07 января 2011

std::vector::erase() не принимает обратный итератор.
Есть ли способ вызвать этот метод с обратным итератором?

Мой пример кода:

std::vector<int> MyVector;
for (int i=0; i<10; i++)
{
    MyVector.push_back(i);
}
// Now suppose that I want to erase the last three elements
int nEraseCount = 0;
for (std::vector<int>::const_reverse_iterator it=MyVector.rbegin();
        it<MyVector.rend(); ++it)
{
    MyVector.erase(it);
    if (++nEraseCount == 3) break;
}

Однако,этот пример кода не работает, поскольку it является обратным итератором, а erase() не принимает обратный итератор в качестве аргумента.

Как изменить этот код, чтобы он работал?

Ответы [ 5 ]

6 голосов
/ 07 января 2011

Вы можете конвертировать из reverse_iterators в итераторы, используя base (), хотя вам нужно вычесть один, чтобы получить тот, который указывает на тот же элемент, таким образом, rbegin () указывает на end () и rend () указывает на begin () (потому что на самом деле невозможно указать на это до начала).

У вас больше проблем, потому что вы используете const_reverse_iterator, который не может быть преобразован в неконстантный, а для удаления требуются неконстантные итераторы. Логика в том, что вы модифицируете коллекцию, поэтому используете неконстантный итератор.

В вашем случае у вас возникла большая проблема с циклом, поскольку вы удаляете итераторы, тем самым делая их недействительными, а затем пытаетесь вернуться к предыдущему элементу.

Если вам нужно удалить последние 3 элемента, вам следует использовать метод стирания, который принимает диапазон, а не удалять их по одному.

Это можно сделать с помощью MyVector.erase(MyVector.rbegin() + 3).base(), MyVector.end() ) в данном конкретном случае, если вы знаете, что MyVector.size() >= 3

5 голосов
/ 07 января 2011

Я бы обошёл проблему, не используя обратный итератор.Я, наверное, напишу что-то подобное:

std::vector<int> MyVector;
for (int i=0; i<10; i++)
{
    MyVector.push_back(i);
}
// Now suppose that I want to erase the last three elements
int nEraseCount = 0;
while (nEraseCount < 3 && !MyVector.empty())
{
    MyVector.pop_back();
    ++nEraseCount;
}
4 голосов
/ 07 января 2011

Хорошо, у вас есть несколько вариантов - вы стираете с конца - чтобы вы могли:

resize()

if (MyVector.size() > 3)
  MyVector.resize(MyVector.size() - 3);
else
  MyVector.clear(); // presumably you don't want all anyway!

простая разница

if (MyVector.size() > 3)
  MyVector.erase(MyVector.end() - 3, MyVector.end());
else
  MyVector.clear(); // presumably you don't want all anyway!

Подход, который вы выбрали, не очень идиоматичен

3 голосов
/ 07 января 2011

Если вы просто хотите удалить N элементов сзади:

size_t N = 3;
size_t to_remove = std::min(vec.size(), N);
vec.erase(vec.end() - to_remove, vec.end());
1 голос
/ 07 января 2011

Вы не можете передать const_iterator или const_reverse_iterator в erase(), так как это readonly итератор!

Вы должны использовать неконстантную forward версия итератора: std::vector<int>::iterator.

...