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

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

Жанры

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

По сравнению с

istream_iterator
это происходит относительно быстро. В проведенных мною простейших тестах выигрыш по скорости достигал 40%, хотя в вашем случае цифры могут быть другими. Не удивляйтесь, если быстродействие будет расти со временем; итераторы
istreambuf_iterator
населяют один из заброшенных уголков STL, и авторы реализаций еще недостаточно позаботились об их оптимизации. Например, в моих примитивных тестах итераторы
istreambuf_iterator
одной из реализаций работали всего на 5% быстрее, чем
istream_iterator
. В таких реализациях остается широкий простор для оптимизации
istreambuf_iterator
.

Если вы планируете читать из потока

по одному символу, не нуждаетесь в средствах форматирования ввода и следите за эффективностью выполняемых операций, три лишних символа на итератор — не такая уж дорогая цена за заметный рост быстродействия. При неформатном посимвольном вводе всегда рассматривайте возможность применения
sreambuf_iterator
.

Раз уж речь зашла о буферизованных итераторах, следует упомянуть и об использовании

ostreambuf_iterator
при неформатном посимвольном выводе. По сравнению с
ostream_iterator
итераторы
ostreambuf_iterator
обладают меньшими затратами (при меньших возможностях), поэтому обычно они превосходят их по эффективности.

Алгоритмы

В начале главы 1 я упоминал о том, что львиная доля репутации STL связана с контейнерами, и это вполне объяснимо. Контейнеры обладают массой достоинств и упрощают повседневную работу бесчисленных программистов C++. Но и алгоритмы STL тоже по-своему замечательны и в той же степени облегчают бремя разработчика. Существует более 100 алгоритмов, и встречается мнение, что они предо-ставляют программисту более гибкий инструментарий по сравнению с контейнерами (которых всего-то восемь!). Возможно, недостаточное применение алгоритмов отчасти и объясняется их количеством. Разобраться в восьми типах контейнеров проще, чем запомнить имена и предназначение многочисленных алгоритмов.

В этой главе я постараюсь решить две основные задачи. Во-первых, я представлю некоторые малоизвестные алгоритмы и покажу, как с их помощью упростить себе жизнь. Не беспокойтесь, вам не придется запоминать длинные списки имен. Алгоритмы, представленные в этой главе, предназначены для решения повседневных задач — сравнение строк без учета регистра символов, эффективный поиск

n
объектов, в наибольшей степени соответствующих заданному критерию, обобщение характеристик всех объектов в заданном интервале и имитация
copy_if
(алгоритм из исходной реализации HP STL, исключенный в процессе стандартизации).

Во-вторых, я научу вас избегать стандартных ошибок, возникающих при работе с алгоритмами. Например, при вызове алгоритма remove и его родственников

remove_if
и
unique
необходимо точно знать, что эти алгоритмы делают (и чего они не делают). Данное правило особенно актуально при вызове
remove
для интервала, содержащего указатели. Многие алгоритмы работают только с отсортированными интервалами, и программист должен понимать, что это за алгоритмы и почему для них установлено подобное ограничение. Наконец, одна из наиболее распространенных ошибок, допускаемых при работе с алгоритмами, заключается в том, что программист предлагает алгоритму записать результаты своей работы в несуществующую область памяти. Я покажу, как это происходит и как предотвратить эту ошибку.

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

Совет 30. Следите за тем, чтобы приемный интервал имел достаточный размер

Контейнеры STL автоматически увеличиваются с добавлением новых объектов (функциями

insert
,
push_front
,
push_back
и т. д.). Автоматическое изменение размеров чрезвычайно удобно, и у многих программистов создается ложное впечатление, что контейнер сам обо всем позаботится и им никогда не
придется следить за наличием свободного места. Если бы так!

Проблемы возникают в ситуации, когда программист думает о вставке объектов в контейнер, но не сообщает о своих мыслях STL. Типичный пример:

int transmogrify(int х); // Функция вычисляет некое новое значение

// по переданному параметру х

vector<int> values;

… // Заполнение вектора values данными

vector<int> results; // Применить transmogrify к каждому объекту

transform(values.begin, // вектора values и присоединить возвращаемые

 values.end, // значения к results.

 results.end, // Фрагмент содержит ошибку!

 transmogrify);

В приведенном примере алгоритм

transform
получает информацию о том, что приемный интервал начинается с
results.end
. С этой позиции он и начинает вывод значений, полученных в результате вызова
transmogrify
для каждого элемента
values
. Как и все алгоритмы, использующие приемный интервал,
transform
записывает свои результаты, присваивая значения элементам заданного интервала. Таким образом,
transform
вызовет
transmogrify
для
values[0]
и присвоит результат
*results.end
. Затем функция
transmogrify
вызывается для
values[1]
с присваиванием результата
*(results.end+1)
. Происходит катастрофа, поскольку в позиции
*results.end
(и тем более в
*(results.end+1))
не существует объекта! Вызов
transform
некорректен из-за попытки присвоить значение несуществующему объекту (в совете 50 объясняется, как отладочная реализация STL позволит обнаружить эту проблему на стадии выполнения).

Допуская подобную ошибку, программист почти всегда рассчитывает на то, что результаты вызова алгоритма будут вставлены в приемный контейнер вызовом

insert
. Если вы хотите, чтобы это произошло, так и скажите. В конце концов, STL — всего лишь библиотека, и читать мысли ей не положено. В нашем примере задача решается построением итератора, определяющего начало приемного интервала, вызовом
back_inserter
:

vector<int> values;

transform(values.begin, // Применить transmogrify к каждому

 values.end, // объекту вектора values

 back_inserter(results), // и дописать значения в конец results

 transmogrify);

При использовании итератора, возвращаемого при вызове

back_inserter
, вызывается
push_back
, поэтому
back_inserter
может использоваться со всеми контейнерами, поддерживающими
push_back
(то есть со всеми стандартными последовательными контейнерами:
vector
,
string
,
deque
и
list
). Если вы предпочитаете, чтобы алгоритм вставлял элементы в начало контейнера, Воспользуйтесь
front_inserter
. Во внутренней реализации
front_inserter
используется
push_front
, поэтому
front_inserter
работает только с контейнерами, поддерживающими эту функцию (то есть
deque
и
list
).

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

Машенька и опер Медведев

Рам Янка
1. Накосячившие опера
Любовные романы:
современные любовные романы
6.40
рейтинг книги
Машенька и опер Медведев

Идущий в тени 4

Амврелий Марк
4. Идущий в тени
Фантастика:
боевая фантастика
6.58
рейтинг книги
Идущий в тени 4

Real-Rpg. Еретик

Жгулёв Пётр Николаевич
2. Real-Rpg
Фантастика:
фэнтези
8.19
рейтинг книги
Real-Rpg. Еретик

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

(Противо)показаны друг другу

Юнина Наталья
Любовные романы:
современные любовные романы
эро литература
5.25
рейтинг книги
(Противо)показаны друг другу

Афганский рубеж

Дорин Михаил
1. Рубеж
Фантастика:
попаданцы
альтернативная история
7.50
рейтинг книги
Афганский рубеж

Последний Паладин. Том 7

Саваровский Роман
7. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 7

Мымра!

Фад Диана
1. Мымрики
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Мымра!

Волк 5: Лихие 90-е

Киров Никита
5. Волков
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Волк 5: Лихие 90-е

Новый Рал

Северный Лис
1. Рал!
Фантастика:
фэнтези
попаданцы
5.70
рейтинг книги
Новый Рал

На границе империй. Том 7. Часть 2

INDIGO
8. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
6.13
рейтинг книги
На границе империй. Том 7. Часть 2

Системный Нуб

Тактарин Ринат
1. Ловец душ
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Системный Нуб

Приручитель женщин-монстров. Том 5

Дорничев Дмитрий
5. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 5

Неверный. Свободный роман

Лакс Айрин
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Неверный. Свободный роман