Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP.doc
Скачиваний:
6
Добавлен:
25.04.2019
Размер:
1.34 Mб
Скачать

// Записать в вектор числа 1 2 3 4

...

// Сортировать по неубыванию

sort (v.begin(), v.end(), not2(less_equal<int>()));

Байндеры – это специальный вид функторов, которые связывают другие функторы со значениями. Например, требуется построить функтор «меньше 3» или «больше 7»; эту задачу можно решить байндером. Ниже приведен пример использования байндера. В примере в контейнере все значения меньшие некоторой границы заменяются этой границей.

vector<int> v;

// Записать в вектор числа 4 6 10 3 13 2

...

int bound = 5; // граница

replace_if(v.begin(), v.end(), bind2nd(less<int>(), bound), bound);

// результат: v == 5 6 10 5 13 5

Байндер bind2nd возвращает новый функтор, требующий только один параметр, поскольку второй был связан с границей bound. При применении полученного функтора к разыменованному итератору i происходит сравнение *i < bound.

Стандартных байндеров в STL всего два: bind1st и bind2nd. Их определения представлены ниже.

template <class Operation, class T>

binder1st<Operation> bind1st(const Operation & op, const T & x)

{

return binder1st<Operation>(op, Operation::first_argument_type(x));

}

template <class Operation, class T>

binder2nd<Operation> bind2nd(const Operation & op, const T & x)

{

return binder2nd<Operation>(op, Operation::second_argument_type(x));

}

Здесь binder1st и binder2nd – это шаблоны классов, которые по существу и выполняют привязку функтора к значению.

Адаптер указателей на функции необходим для преобразования обычного функционального вызова в обращение к соответствующему функтору. Этот адаптер задается шаблоном ptr_fun и принимает в качестве аргумента любую унарную или бинарную функцию, возвращая соответствующий ей функтор. Полученный функтор осуществляет просто вызов функции, из которой он был получен. Ниже дан пример, в котором выполняется лексикографическая сортировка массива строк. Сортировка реализована алгоритмом sort, при этом лексикографический порядок задается стандартной функцией strcmp, преобразованной в функтор.

vector<char*> v;

char * c1 = new char[10]; strcpy (c1, "baa");

char * c2 = new char[10]; strcpy (c2, "abc");

char * c3 = new char[10]; strcpy (c3, "aad");

v.push_back(c1);

v.push_back(c2);

v.push_back(c3);

sort (v.begin(), v.end(), ptr_fun(strcmp));

copy (v.begin(), v.end(), ostream_iterator<char*> (cout, " "));

...

delete[] c1;

delete[] c2;

delete[] c3;

// результат: aad abc baa

9.8. Аллокаторы

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

Как правило, параметры-аллокаторы имеют значения по умолчанию (см. выше) и их явное указание избыточно. Тем самым от пользователя скрывается семантика управления памятью в контейнерах. При необходимости, однако, указание особых аллокаторов в параметрах шаблонов возможно. В следующем небольшом примере создается список в условиях дальней модели памяти:

#include <faralloc.h> // для far_allocator

#include <list.h>

...

list <int, far_allocator> fl;

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]