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

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

Жанры

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

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

Мастер 3

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

Бастард

Майерс Александр
1. Династия
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард

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

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

Дважды одаренный. Том VI

Тарс Элиан
6. Дважды одаренный
Фантастика:
аниме
альтернативная история
фэнтези
фантастика: прочее
5.00
рейтинг книги
Дважды одаренный. Том VI

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

Винокуров Юрий
22. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXII

Низший - Инфериор. Компиляция. Книги 1-19

Михайлов Дем Алексеевич
Фантастика 2023. Компиляция
Фантастика:
боевая фантастика
5.00
рейтинг книги
Низший - Инфериор. Компиляция. Книги 1-19

Гром Раскатного. Том 2

Володин Григорий Григорьевич
2. Штормовой Предел
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Гром Раскатного. Том 2

Князь

Шмаков Алексей Семенович
5. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
сказочная фантастика
5.00
рейтинг книги
Князь

Третий. Том 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 3

Менталист. Революция

Еслер Андрей
3. Выиграть у времени
Фантастика:
боевая фантастика
5.48
рейтинг книги
Менталист. Революция

Analyste

Мелехов Андрей Михайлович
Аналитик
Фантастика:
социально-философская фантастика
юмористическая фантастика
6.57
рейтинг книги
Analyste

Вернувшийся: Новая жизнь. Том I

Vector
1. Вернувшийся
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Вернувшийся: Новая жизнь. Том I

Бастард Бога (Дилогия)

Матвеев Владимир
Фантастика:
альтернативная история
5.11
рейтинг книги
Бастард Бога (Дилогия)

Принадлежать им

Зайцева Мария
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Принадлежать им