2012-04-29 3 views
1

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

int main() 
{ 
    vector<int> v; 

    for(int i = 0; i < 10; ++i) 
     v.push_back(i); 

    auto it = v.begin() + 3; 

    cout << "Iterator: " << *it << endl; 

    vector<int>::reverse_iterator revIt(it); 

    cout << "Reverse iterator: " << *revIt << endl; 

} 

После выполнения этого кода я получаю следующий результат:

Iterator: 3 
Reverse iterator: 2 

Может кто-нибудь объяснить, почему 2 значения отличаются ?

+0

Я не уверен на 100%, но итератор вперед будет смотреть вперед, тогда как обратный итератор будет оглядываться назад. 'v = {1, 2, * 3, 4 ...}' где * - итераторная позиция обоих из них. Посмотрите, в каком направлении они идут. – chris

+0

@chris: не совсем: или лучше, так как java определяет итераторы (указывая «между ними»). C++ имеет другую концепцию. Но практический результат также соответствует вашему объяснению. Но это следствие, а не определение. –

+0

@EmilioGaravaglia, спасибо, что расчистили его. Я не очень хорошо знаком. – chris

ответ

5

обратных итераторы «соответствуют» к base итератору со смещением одного элемента из-за того, как rbegin() и rend() должны быть представлены с использованием базовых итераторов, которые являются действительными (end() и begin() соответственно). Например, rend() не может быть представлен инсайтором, который «указывает» перед итератором begin() контейнера, хотя это то, что он логически представляет. Таким образом, базовый итератор rend() равен begin(). Следовательно, базовый итератор rbegin() становится end(). Обратный итератор автоматически настраивает для этого смещения, когда он разыменован (с использованием операторов * или ->).

старый article by Scott Meyers объясняет отношения в деталях вместе с красивой картинки:

Руководящий принцип 3: Понять, как использовать reverse_iterator в базовый итератор

Вызов функции базового члена на reverse_iterator урожайности «соответствующий» итератор, но это не совсем понятно, что это значит. В качестве примера, посмотрите на этот код, который помещает число 1-5 в вектор, задает reverse_iterator, указывающую на 3, и устанавливает итератор на базу reverse_iterator в:

vector<int> v; 

// put 1-5 in the vector 
for (int i = 1; i <= 5; ++i) { 
    v.push_back(i); 
} 

// make ri point to the 3 
vector<int>::reverse_iterator ri = 
    find(v.rbegin(), v.rend(), 3); 

// make i the same as ri's base 
vector<int>::iterator i(ri.base()); 

После выполнения этого кода, то можно думать, как смотреть, как этого:

alt text

Эта картина хороша, отображая характеристики смещения в reverse_iterator и его соответствующег ng base, который имитирует смещение rbegin() и rend() по отношению к begin() и end(), но не сообщает вам все, что вам нужно знать. В частности, он не объясняет, как использовать i для выполнения операций, которые вы хотели бы выполнить выполнить на ri.

4

Похоже, что documentation говорит, что они делают это для обработки сквозных элементов, т. Е. Если вы отменили итератор, который находится за концом, новый обратный итератор указывает на последний элемент.

2

Первый пункт 24.5.1 Обратного итераторы говорит:

шаблон класса reverse_iterator представляет собой адаптер итератора, который выполняет итерацию от конца последовательности, определенной с помощью лежащего в его основе итератора к началу этой последовательности. Фундаментальное соотношение между обратным итератором и его соответствующим итератором i устанавливается тождеством:
&*(reverse_iterator(i)) == &*(i - 1).

Значение, возвращаемое rend(), не может быть указано до begin(), потому что это неверно. Поэтому было решено, что rend() должно содержать значение begin(), а все остальные обратные итераторы будут сдвинуты на одну позицию дальше. operator* компенсирует это и в любом случае получает доступ к правильному элементу.

1

обратный итератор выглядит всегда «один, прежде чем», то вперед, так как его диапазон сдвигается на одну:

вперед итератор идет от начать() (первый элемент) до конца() (в прошлом последнего : [начать-конец) открывается на торцевой стороне)

обратного итератора идет от rbegin() { return reverse_iterator(end()); } к rend() { return reverse_iterator(begin()); } по определению, но и должен пройти открытый диапазон [rbegin-REND), имеющий rbegin быть последним (не «прошлое последний ") и раздираться, чтобы быть" до первого "(а не" первым "), следовательно, 1 разницу, которая должна быть размещена.

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