2016-11-19 2 views
2

Для упрощения моего вопроса я буду использовать std::string::iterator и std::string::reverse_iterator, но вопрос об итераторах в целом.Итерация назад с использованием итераторов

Есть ли конкретная причина для перебора в обратном направлении, используя следующий цикл:

std::string s = "something"; 
for (std::string::reverse_iterator it = s.rbegin(); it != s.rend(); ++it) 

, а не этого одного:

std::string s = "something"; 
std::string::iterator it = in.end(); 
while(it!=in.begin()) 
{ 
    it--; 
    //do something 
} 

ответ

4

Обратные итераторы позволяют повторно использовать общий код, потому что вы можете относиться к ним, как обычные итераторы, вызывая ++ идти в обратном направлении. Например:

#include <iostream> 
#include <string> 

template <class Iterator> 
void printAll(Iterator begin, Iterator end) 
{ 
    for (auto it = begin; it != end; ++it) // ++ can mean "go backwards" 
              // if Iterator is a reverse 
              // iterator 
    { 
     std::cout << *it << "\n"; 
    } 
} 

int main() 
{ 
    std::string s = "123"; 
    printAll(s.begin(), s.end()); // prints 1, 2, 3 
    printAll(s.rbegin(), s.rend()); // prints 3, 2, 1 
} 

Обратите внимание, как вам не нужно, чтобы написать обратную версию для printAll с помощью --.

Теперь рассмотрим все функции в <algorithm>. Существование обратных итераторов означает, что вы можете легко использовать их все в обратном порядке. Например, есть std::copy_n, но не std::reverse_copy_n, но с обратными итераторами, это не нужно, потому что вы можете написать что-то вроде этого:

#include <iostream> 
#include <string> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    std::string input = "abcdef"; 
    std::string output; 
    std::string output_reversed; 

    // copy the first 3 elements: 
    std::copy_n(input.begin(), 3, std::back_inserter(output)); 

    // copy the first 3 elements going backwards, starting at the last one: 
    std::copy_n(input.rbegin(), 3, std::back_inserter(output_reversed)); 

    std::cout << output << "\n";   // prints abc 
    std::cout << output_reversed << "\n"; // prints fed 
} 

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

+0

Спасибо за четкое объяснение! – theVoid

+1

Это хороший ответ, потому что на самом деле он не просто отвечает на вопрос (к которому совершенно правильный ответ был бы * Нет *), но более фундаментальный (и лучший) вопрос * В чем смысл 'reverse_iterator'? * – Walter

1

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

std::vector::end() at cplusplus.com

+2

'in.begin() - 1' Нет, нет, нет, в тысячу раз нет. –

+0

Я не рекомендовал его, но иногда он может работать. – sandyre

+0

@sandyre Я считаю, что мой цикл while делает то, что ожидается, так как я его протестировал. – theVoid

Смежные вопросы