Вспомогательные функции итераторов. Перебор итераторов функцией advance()

   
На этом шаге мы рассмотрим использование функции advance().

   
Стандартная библиотека C++ содержит три вспомогательные функции для работы с итераторами:
advance(), distance() и iter_swap().
Первые две функции предоставляют для любого итератора возможности, которыми обычно обладают только
итераторы произвольного доступа: перемещение итератора сразу на несколько элементов вперед (или назад) и
вычисление разности между итераторами. Третья вспомогательная функция меняет местами элементы, на
которые ссылаются два итератора.
Перебор итераторов функцией advance()

   
Функция advance() перемещает итератор, передаваемый ей в качестве аргумента. При этом смещение может
производиться в прямом (или обратном) направлении сразу на несколько элементов:

  #include <iterator>
  void advance (InputIterator& pos, Dist n)

   
Перемещает итератор ввода pos на n элементов вперед (или назад). Для двунаправленных итераторов и
итераторов произвольного доступа значение n может быть отрицательным (перемещение в обратном
направлении).

   
Dist - тип шаблона. Обычно является целым типом, поскольку для него вызываются такие операции, как
<, ++, -- и сравнение с 0.

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

   
Благодаря разным трактовкам итераторов функция всегда использует оптимальную реализацию в зависимости от
категории итератора. Для итераторов произвольного доступа она просто вызывает pos+=n. Следовательно,
для таких итераторов функция advance() имеет постоянную сложность. Для остальных итераторов
используется n-кратный вызов pos (или --pos, если значение n отрицательно).
Таким образом, для всех остальных категорий итераторов функция advance() выполняется с линейной сложностью.

   
Чтобы иметь возможность свободно менять типы контейнера и итератора, используйте функцию advance()
вместо оператора +=. Однако следует помнить, что при этом возможно непредвиденное снижение быстродействия
при переходе на другие типы контейнеров, не поддерживающие итераторы произвольного доступа (именно из-за
снижения быстродействия оператор += применяется только для итераторов произвольного доступа). Также
помните, что функция advance() не возвращает значения, а оператор += возвращает новую позицию и может
входить в более сложное выражение. Пример использования функции advance():

//---------------------------------------------------------------------------

#include <vcl.h>
#include <iostream>
#include <iterator>
#include <list>
#include <algorithm>

#include <conio.h> //необходимо для getch()

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;


std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}


int main(int argc, char* argv[])
{
  list<int> coll;
  
  // Вставка элементов от 1 до 9 
  for (int i=1; i<=9; ++i) {
    coll.push_back(i); 
  }

  list<int>::iterator pos = coll.begin();

  // Вывод текущего элемента 
  cout << ToRus("Текущий элемент: ");
  cout << *pos << endl;

  // Перемещение вперед на три элемента 
  advance (pos, 3);

  // Вывод текущего элемента 
  cout << ToRus("Текущий элемент: ");
  cout << *pos << endl;

  // Перемещение назад на один элемент 
  advance (pos, -1);
  // Вывод текущего элемента 
  cout << ToRus("Текущий элемент: ");
  cout << *pos << endl;

  getch();
  return 0;
}

//---------------------------------------------------------------------------

Текст этого примера можно взять здесь.

   
Вызовы advance() переводят итератор на три элемента вперед и на один элемент назад. Результат:


Рис.1. Результат работы приложения

   
Существуют и другие применения функции advance(). Например, вы можете проигнорировать часть ввода от
итераторов, читающих данные из входного потока.

   
На следующем шаге мы рассмотрим функцию distance().



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий