Программирование >>  Оптимизация возвращаемого значения 

1 ... 87 88 89 [ 90 ] 91 92 93 ... 96


while (begin != end && *begin != value) ++begin; return begin;

Обратите внимание: при преобразовании в шаблон вместо передачи value по значению выполняется передача по ссылке на const. Это связано с тем, что теперь передаются произвольные типы, и поэтому приходится учитывать затраты на передачу по значению. Для каждого передаваемого по значению параметра приходится вызывать его конструктор и деструктор при всяком вызове функции. Чтобы избежать этих затрат, надо использовать передачу по ссылке, исключая создание и удаление объекта.

Этот шаблон достаточно хорош, но его можно еще ул5шить. Посмотрите на операции с begin и end. Из них используются только сравнение на равенство и неравенство, разыменование, префиксный инкремент (см. правило 6) и копирование (для возвращаемого значения функции - см. правило 19). Все эти операции можно перегрузить, поэтому зачем ограничивать функцию find работой с указателями? Почему не разрешить использование не только указателей, но и любых других объектов, поддерживающих эти операции? В результате вы освободите функцию find от встроенного значения операций с указателями. Например, можно будет определить похожий на указатель объект для связного списка, префиксный оператор инкремента которого перемещал бы вас на следующий элемент в списке.

Эта концепция и лежит в основе итераторов STL. Итераторы - это, как уже говорилось, похожие на указатели объекты, предназначенные для использования с контейнерами STL. Они близкие родственники интеллектуальных указателей, описанных в правиле 28, но последние обычно более амбициозны . С технической точки зрения и те, и другие реализуются при помощи одинаковых методов.

Рассматривая итераторы как похожие на указатели объекты, можно заменить в функции find указатели на итераторы, переписав функцию find:

template<class Iterator, class Т>

Iterator find(Iterator begin, Iterator end, const T& value) {

while (begin != end && *begin != value) ++begin; return begin;

Поздравляю! Вы только что написали часть стандартной библиотеки шаблонов. Она содержит десятки алгоритмов, работающих с контейнерами и итераторами, и функция find является одним из них.

Контейнеры в STL имеют типы bitset, vector, list, deque, queue, priority queue, stack, set и map, и вы можете применять функцию find к любому из этих типов:

list<char> charList; Создать объект STL

для списка символов.

Найти положение первого символа х в charList.



list<char>::iterator it = find(charList.begin{), charList.endO , X ) ;

Постойте! , - кричите вы, - Это совсем не похоже на предыдущие примеры массивов! . Нет, они похожи; вы просто должны знать, в чем искать это сходство.

Для вызова функции find для объекта list вам нужны итераторы, указывающие на первый элемент списка и на элементрасположенный сразу же за концом списка. Без помощи со стороны класса list это было бы нелегкой задачей, так как реализация list не известна. К счастью, класс list (как и все контейнеры STL) должен содержать функции-члены begin и end. Эти функции-члены возвращают нужные вам итераторы, которые и передаются в качестве двух первых параметров функции find в примере.

Завершив свое выполнение, функция find возвращает объект-итератор, указывающий на найденный элемент (если он существует) или на charList. end () (если искомого элемента нет в списке). Поскольку вы ничего не знаете о реализации класса list, то вы ничего не знаете и о реализации итераторов в list. Как тогда вы сможете выяснить тип объекта, возвращаемого функцией find? И снова вам на помощь приходит класс list, который, как и все контейнеры STL, содержит определение типа iterator, соответствующее типу итераторов в 1 i s t. Так как объект charList является списком символов, то итераторы для такого списка имеют тип list<char>::iterator, и именно этот тип используется в вышеприведенном примере. (На самом деле в каждом классе-контейнере STL определяются два типа итераторов, iterator и const iterator. Первый из них выступает в качестве обычного указателя, а последний - в качестве указателя на const.)

Такой же подход может использоваться и для других контейнеров STL. Кроме того, указатели С++ также являются итераторами STL, поэтому исходные примеры работы с массивами будут работать с функцией find из STL:

int values[50] ;

int *firstFive = find(values, Нормально,

values+50, вызывает функцию

5) ; find из STL.

Принцип организации стандартной библиотеки шаблонов очень прост. Она представляет собой набор шаблонов классов и функций, придерживающихся ряда соглашений. Набор классов STL содержит функции, такие как begin и end, которые возвращают объекты-итераторы определенных в классе типов. Функции алгоритмов STL перемещаются между наборами объектов, используя объекты итераторы для наборов STL. Итераторы STL работают как указатели. Вот в сущности, и все. Нет большой иерархии наследования, нет виртуальных функций и того подобного. Просто несколько шаблонов классов и функций и набор соглашений, которых они придерживаются.



Это приводит к новому откровению: стандартная библиотека шаблонов является расширяемой. Вы можете добавлять к семейству STL свои наборы, алгоритмы и итераторы. До тех пор пока вы следуете соглашениям STL, стандартные наборы STL будут работать с вашими алгоритмами, а ваши наборы со стандартными алгоритмами STL. Конечно, ваши шаблоны не станут частью стандартной библиотеки C-I-I-, но они будут построены на тех же принципах, что позволит использовать их повторно.

Библиотека C-i-i- содержит намного больше возможностей, чем описано в этой книге. Поэтому чтобы эффективно использовать ее, обратитесь к другим источникам информации (их список приведен в приложении 1), где вы найдете подробные сведения как о библиoтeкe,taк и о соглашениях STL. Стандартная библиотека С++ намного богаче библиотеки С, и время, которое вы потратите на ознакомление с ней, будет потрачено не напрасно. Кроме того, воплощенные в библиотеке принципы разработки - универсальность, расширяемость, эффективность, возможность настройки и повторного использования - сами по себе стоят вашего внимания. Из5ая стандартную библиотеку С++, вы не только пополните ваши знания о готовых компонентах, которые сможете использовать в своих программах, но и поймете, как более эффективно применять С++ и разрабатывать собственные библиотеки.



1 ... 87 88 89 [ 90 ] 91 92 93 ... 96

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика