Использовать обычный итератор для итерации в обратном направлении или бороться с reverse_iterator? - PullRequest
9 голосов
/ 05 декабря 2009

Недавно я узнал о правильном способе работы с обратными итераторами в C ++ (особенно, когда вам нужно стереть один). (См. этот вопрос и этот .)

Вот как вы должны это сделать:

typedef std::vector<int> IV;
for (IV::reverse_iterator rit = iv.rbegin(), rend = iv.rend();
     rit != rend; ++rit)
{
  // Use 'rit' if a reverse_iterator is good enough, e.g.,
  *rit += 10;
  // Use (rit + 1).base() if you need a regular iterator e.g.,
  iv.erase((rit + 1).base());
}

Но я думаю думал, что это намного лучше ( Не делайте этого , не соответствует стандартам, как указывает MooingDuck):

for (IV::iterator it = iv.end(), begin = iv.begin();
     it-- != begin; )
{
  // Use 'it' for anything you want
  *it += 10;
  iv.erase(it);
}

Минусы:

  • Вы говорите мне. Что с ним не так?
  • Это не соответствует стандартам, как указывает MooingDuck. Это в значительной степени отменяет любое из возможных преимуществ ниже.

Плюсы:

  • Использует знакомую идиому для обратных циклов for
  • Не нужно помнить (или объяснять) +1
  • Меньше печатать
  • Работает и для std :: list: it = il.erase(it);
  • Если вы удалите элемент, вам не нужно настраивать итератор
  • Если вы удалите, вам не нужно пересчитывать начальный итератор

Ответы [ 2 ]

7 голосов
/ 07 декабря 2009

Причина обратных итераторов в том, что стандартные алгоритмы не знают, как перебирать коллекцию в обратном направлении. Например:

#include <string>
#include <algorithm>
std::wstring foo(L"This is a test, with two letter a's involved.");
std::find(foo.begin(), foo.end(), L'a'); // Returns an iterator pointing
                                        // to the first a character.
std::find(foo.rbegin(), foo.rend(), L'a').base()-1; //Returns an iterator
                                                 // pointing to the last A.
std::find(foo.end(), foo.begin(), L'a'); //WRONG!! (Buffer overrun)

Использование любого итератора приводит к более ясному коду.

3 голосов
/ 05 декабря 2009

Что бы это ни стоило, Скотт Мейерс Effective STL рекомендует вам просто придерживаться обычного старого * iterator (пункт 26).

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