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

на главную

Жанры

Эффективное использование 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;

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

Кодекс Крови. Книга VIII

Борзых М.
8. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VIII

Камень

Минин Станислав
1. Камень
Фантастика:
боевая фантастика
6.80
рейтинг книги
Камень

Партиец

Семин Никита
2. Переломный век
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Партиец

Он тебя не любит(?)

Тоцка Тала
Любовные романы:
современные любовные романы
7.46
рейтинг книги
Он тебя не любит(?)

Бестужев. Служба Государевой Безопасности

Измайлов Сергей
1. Граф Бестужев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности

Хозяйка брачного агентства или Попаданка в поисках любви

Максонова Мария
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка брачного агентства или Попаданка в поисках любви

Возрождение Феникса. Том 1

Володин Григорий Григорьевич
1. Возрождение Феникса
Фантастика:
фэнтези
попаданцы
альтернативная история
6.79
рейтинг книги
Возрождение Феникса. Том 1

Релокант. Вестник

Ascold Flow
2. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант. Вестник

Книга пяти колец. Том 3

Зайцев Константин
3. Книга пяти колец
Фантастика:
фэнтези
попаданцы
аниме
5.75
рейтинг книги
Книга пяти колец. Том 3

Идеальный мир для Лекаря 8

Сапфир Олег
8. Лекарь
Фантастика:
юмористическое фэнтези
аниме
7.00
рейтинг книги
Идеальный мир для Лекаря 8

Идеальный мир для Социопата 6

Сапфир Олег
6. Социопат
Фантастика:
боевая фантастика
рпг
6.38
рейтинг книги
Идеальный мир для Социопата 6

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3

Прометей: повелитель стали

Рави Ивар
3. Прометей
Фантастика:
фэнтези
7.05
рейтинг книги
Прометей: повелитель стали

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

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