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

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

Жанры

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

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

BPFC
, то вам пришлось бы позаботиться о том, чтобы копирующий конструктор выполнял осмысленные действия с объектом
BPFCImpl
, на который он ссылается. Возможно, простейшее решение заключается в организации подсчета ссылок при помощи указателя
shared_ptr
из библиотеки
Boost
или его аналога (см. совет 50).

В сущности, копирующий конструктор

BPFC
— единственное, о чем вам придется побеспокоиться в контексте данного примера, поскольку при передаче и получении функторов от функций STL всегда происходит копирование (помните, что говорилось выше о передаче по значению?). Из этого вытекают два требования: компактность и мономорфизм.

Совет 39. Реализуйте предикаты в виде «чистых» функций

Для начала разберемся с основными терминами.

• Предикатом называется функция, возвращающая тип

bool
(или другое значение, которое может быть автоматически преобразовано к
bool
). Предикаты широко используются в STL. В частности, функции сравнения в стандартных ассоциативных контейнерах представляют собой предикаты. Предикатные функции часто передаются в виде параметров таким алгоритмам, как
find_if
, и различным алгоритмам сортировки (обзор алгоритмов сортировки приведен в совете 31).

• «Чистой» функцией называется функция, возвращаемое значение которой зависит только от параметров. Если

f
— «чистая» функция, а 
x
и 
y
— объекты, то возвращаемое значение
f(x, y)
может измениться только в случае изменения х или у.

В C++ все данные, используемые «чистыми» функциями, либо передаются в виде параметров, либо остаются постоянными на протяжении всего жизненного цикла функции (естественно, такие постоянные данные объявляются с ключевым словом const). Если бы данные, используемые «чистой» функцией, могли изменяться между вызовами, то вызов этой функции в разные моменты времени с одинаковыми параметрами мог бы давать разные результаты, что противоречит определению «чистой» функции.

Из сказанного должно быть понятно, что нужно сделать, чтобы предикаты были «чистыми» функциями. Мне остается лишь убедить читателя в том, что эта рекомендация обоснована. Для этого придется ввести еще один термин.

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

operator
является предикатом, то есть возвращает
true
или
false
. Как и следует ожидать, во всех случаях, когда STL ожидает получить предикат, может передаваться либо настоящий предикат, либо объект предикатного класса.

Обещаю, что новых терминов больше не будет. Теперь давайте разберемся,

почему следует выполнять рекомендацию данного совета.

В совете 38 объяснялось, что объекты функций передаются по значению, поэтому при проектировании необходимо позаботиться о возможном копировании. Для объектов функций, являющихся предикатами, существует и другой аргумент в пользу специальной поддержки копирования. Алгоритмы могут создавать копии функторов и хранить их определенное время перед применением, причем некоторые реализации алгоритмов этим активно пользуются. Важнейшим следствием этого факта является то, что предикатные функции должны быть «чистыми».

Предположим, вы нарушили это ограничение. Ниже приведен плохо спроектированный класс предиката, который независимо от переданных аргументов возвращает

true
только один раз — при третьем вызове. Во всех остальных случаях возвращается
false
.

class BadPredicate: // Базовый класс описан

 public unary_function<Widget, bool>{ // в совете 40

public:

 BadPredicate: timesCalles(0) {} // Переменная timesCalled

// инициализируется нулем

bool operator(const Widget&) {

 return ++timesCalled = 3;

}

private:

 size_t timesCalled;

};

Предположим, класс

BadPedicate
используется для исключения третьего объекта
Widget
из контейнера
vector<Widget>
:

vector<Widget> vw; // Создать вектор и заполнить его

… // объектами Widget

vww.erase(remove_if(vw.begin, // Удалить третий объект Widget.

 vw.end, // связь между erase и remove_if

 BadPredcate), // описана в совете 32

 vw.end);

Программа выглядит вполне разумно, однако во многих реализациях STL из вектора

vw
удаляется не только третий, но и шестой элемент!

Чтобы понять, почему это происходит, необходимо рассмотреть один из распространенных вариантов реализации

remove_if
. Помните, что эта реализация не является обязательной.

template<typename FwdIterator, typename Predicate>

FwdIterator remove_if(FwdIterator begin, FwdIterator end, Predicate p) {

 begin = find_if(begin, end, p);

 if (begin==end) return begin;

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

Измена. (Не)любимая жена олигарха

Лаванда Марго
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха

Хозяйка дома в «Гиблых Пределах»

Нова Юлия
Любовные романы:
любовно-фантастические романы
5.75
рейтинг книги
Хозяйка дома в «Гиблых Пределах»

Фиктивный брак

Завгородняя Анна Александровна
Фантастика:
фэнтези
6.71
рейтинг книги
Фиктивный брак

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

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

Держать удар

Иванов Дмитрий
11. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Держать удар

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Драконий подарок

Суббота Светлана
1. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
7.30
рейтинг книги
Драконий подарок

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

По дороге на Оюту

Лунёва Мария
Фантастика:
космическая фантастика
8.67
рейтинг книги
По дороге на Оюту

Мастер 5

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

Не лечи мне мозги, МАГ!

Ордина Ирина
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.00
рейтинг книги
Не лечи мне мозги, МАГ!

Измена. Право на семью

Арская Арина
Любовные романы:
современные любовные романы
5.20
рейтинг книги
Измена. Право на семью

Крепость над бездной

Лисина Александра
4. Гибрид
Фантастика:
боевая фантастика
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Крепость над бездной

Неудержимый. Книга XXI

Боярский Андрей
21. Неудержимый
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Неудержимый. Книга XXI