Вход/Регистрация
Эффективное использование STL
вернуться

Мейерс Скотт

Шрифт:

Все хорошо, если бы этот вариант компилировался… но этого не происходит. Чтобы понять причины, рассмотрим объявление

distance
:

template<typename InputIterator>

typename iterator_traits<InputIterator>::difference_type

distance(InputIterator first, InputIterator last);

Не обращайте внимания на то, что тип возвращаемого значения состоит из 56 символов и содержит упоминания зависимых типов (таких как differenceype). Вместо этого проанализируем использование параметра-типа

InputIterator
:

template<typename InputIterator>

typename iterator_traits<InputIterator>::difference_type

distance(InputIterator first, InputIterator last);

При вызове

distance
компилятор должен определить тип, представленный
InputIterator
, для чего он анализирует аргументы, переданные при вызове. Еще раз посмотрим на вызов
distance
в приведенном выше коде:

advance(i, distance(i,ci)); // Переместить i в позицию ci

При вызове передаются два параметра,

i
и
ci
. Параметр
i
относится к типу
iter
, который представляет собой определение типа для
deque<int>::iterator
. Для компилятора это означает, что
InputIterator
при вызове
distance
соответствует типу
deque<int>::iterator
. Однако
ci
относится к типу
ConstIter
, который представляет собой определение типа для
deque<int>::const_iterator
. Из этого следует, что
InputIterator
соответствует типу
deque<int>::const_iterator
.
InputIterator
никак не может соответствовать двум типам одновременно, поэтому вызов
distance
завершается неудачей и каким-нибудь запутанным сообщением об ошибке, из которого можно (или нельзя) понять, что компилятор не смог определить тип
InputIterator
.

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

distance
, и избавить компилятор от необходимости определять его самостоятельно:

advanced.distance<ConstIter>(i, ci)); // Вычислить расстояние между

// i и ci (как двумя const_iterator)

// и переместить i на это расстояние

Итак, теперь вы знаете, как при помощи

advance
и
distance
получить
iterator
, соответствующий заданному
const_iterator
, но до настоящего момента совершенно не рассматривался вопрос, представляющий большой практический интерес: насколько эффективна данная методика? Ответ прост: она эффективна настолько, насколько это позволяют итераторы. Для итераторов произвольного доступа, поддерживаемых контейнерами
vector
,
string
,
deque
и т. д., эта операция выполняется с постоянным временем. Для двусторонних итераторов (к этой категории относятся итераторы других стандартных контейнеров, а также некоторых реализаций хэшированных контейнеров — см. совет 25) эта операция выполняется с линейным временем.

Поскольку получение

iterator
, эквивалентного
const_iterator
, может потребовать линейного времени, и поскольку это вообще невозможно сделать при недоступности контейнера, к которому относится
const_iterator
, проанализируйте архитектурные решения, вследствие которых возникла необходимость получения
iterator
по
const_iterator
. Результат такого анализа станет дополнительным доводом в пользу совета 26, рекомендующего отдавать предпочтение
iterator
перед
const
– и
reverse
– итераторами.

Совет 28. Научитесь использовать функцию base

При вызове функции

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

vector<int> v;

v.reserve(5); //См. совет 14

for (int i=1; i<=5; ++i){ // Занести в вектор числа 1-5

 v.push_back(i);

}

vector<int>::reverse_iterator ri = // Установить ri на элемент 3

 find(v.rbegin, v.rend, 3);

vector<int>::iterator i(ri.base); // Присвоить i результат вызова base

// для итератора ri

  • Читать дальше
  • 1
  • ...
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: