Чтение онлайн

на главную - закладки

Жанры

Эффективное использование STL
Шрифт:

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

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

На рисунке видно характерное смещение

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

Как упоминалось в совете 26, некоторые функции контейнеров принимают в качестве параметров-итераторов только

iterator
. Поэтому если вы, допустим, захотите вставить новый элемент в позицию, определяемую итератором
ri
, сделать это напрямую не удастся; функция
insert
контейнера
vector
не принимает
reverse_iterator
. Аналогичная проблема возникает при удалении элемента, определяемого итератором
ri
. Функции erase не соглашаются на
reverse_iterator
и принимают только
iterator
. Чтобы выполнить удаление или вставку, необходимо преобразовать
reverse_iterator
в
iterator
при помощи
base
, а затем воспользоваться iterator для выполнения нужной операции.

Допустим, потребовалось вставить в

v
новый элемент в позиции, определяемой итератором
ri
. Для определенности будем считать, что вставляется число 99. Учитывая, что 
ri
на предыдущем рисунке используется для перебора справа налево, а новый элемент вставляется перед позицией итератора, определяющего позицию вставки, можно ожидать, что число 99 окажется перед числом 3 в обратном порядке перебора. Таким образом, после вставки вектор
v
будет выглядеть так:

Конечно, мы не можем использовать 

ri
для обозначения позиции вставки, поскольку это не
iterator
. Вместо этого необходимо использовать
i
. Как упоминалось выше, когда
ri
указывает на элемент 3,
i
(то есть
r. base
) указывает на элемент 4. Именно на эту позицию должен указывать итератор
i
, чтобы вставленный элемент оказался в той позиции, в которой он бы находился, если бы для вставки можно было использовать итератор
ri
. Заключение:

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

Цветы сливы в золотой вазе, или Цзинь, Пин, Мэй

Ланьлинский насмешник
Старинная литература:
древневосточная литература
7.00
рейтинг книги
Цветы сливы в золотой вазе, или Цзинь, Пин, Мэй

Кодекс Охотника. Книга XIX

Винокуров Юрий
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XIX

70 Рублей - 2. Здравствуй S-T-I-K-S

Кожевников Павел
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
постапокалипсис
5.00
рейтинг книги
70 Рублей - 2. Здравствуй S-T-I-K-S

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Лучше подавать холодным

Аберкромби Джо
4. Земной круг. Первый Закон
Фантастика:
фэнтези
8.45
рейтинг книги
Лучше подавать холодным

Имперец. Земли Итреи

Игнатов Михаил Павлович
11. Путь
Фантастика:
героическая фантастика
боевая фантастика
5.25
рейтинг книги
Имперец. Земли Итреи

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2

Не грози Дубровскому!

Панарин Антон
1. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому!

Отмороженный 7.0

Гарцевич Евгений Александрович
7. Отмороженный
Фантастика:
рпг
аниме
5.00
рейтинг книги
Отмороженный 7.0

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита

Энфис 5

Кронос Александр
5. Эрра
Фантастика:
героическая фантастика
рпг
аниме
5.00
рейтинг книги
Энфис 5

Опасная любовь командора

Муратова Ульяна
1. Проклятые луной
Фантастика:
фэнтези
5.00
рейтинг книги
Опасная любовь командора

Найди меня Шерхан

Тоцка Тала
3. Ямпольские-Демидовы
Любовные романы:
современные любовные романы
короткие любовные романы
7.70
рейтинг книги
Найди меня Шерхан