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

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

Жанры

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

 void operator(int x){…} // в совете 40

};

typedef deque<int>::iterator DequeIntIter; // Вспомогательное определение

deque<int> di;

DoSomething d; // Создать объект функции

for_each<DequeIntIter, // Вызвать for_each с типами

 DoSomethng&>(di.begin, //
параметров DequeIntIter

 di.end, // и DoSomething&; в результате

 d); // происходит передача

// и возврат по ссылке.

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

Поскольку объекты функций передаются и возвращаются по значению, вы должны позаботиться о том, чтобы объект функции правильно работал при передаче подобным способом (то есть копированием). Для этого необходимо соблюдение двух условий. Во-первых, объекты функций должны быть небольшими, в противном случае копирование обойдется слишком дорого. Во-вторых, объекты функций должны быть мономорфными (то есть не полиморфными), поэтому в них не могут использоваться виртуальные функции. Второе требование связано с тем, что при передаче по значению объектов производных классов в параметрах базового класса происходит отсечение: в процессе копирования удаляются специализированные составляющие (другой пример проблемы отсечения в STL приведен в совете 3).

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

Столь же нереалистичен и запрет на полиморфные функторы. Иерархическое наследование и динамическое связывание относятся к числу важнейших особенностей C++, и при проектировании классов функторов они могут принести такую же пользу, как и в других областях. Что такое классы функторов без наследования? C++ без «++». Итак, необходимы средства, которые бы позволяли легко передавать большие и/или полиморфные объекты функций с соблюдением установленного в STL правила о передаче функторов по значению.

Такие средства действительно существуют. Достаточно взять данные и/или полиморфные составляющие, которые требуется сохранить в классе функтора, перенести их в другой класс и сохранить в классе функтора указатель на этот новый класс. Рассмотрим пример создания класса полиморфного функтора с большим количеством данных:

template<typename T> // BPFC = "Big Polymorphic

class BPFC: // Functor class"

 public // Базовый класс описан

 unary_function<T, void> { // в совете 40

private:

 Widget w; //
Класс содержит большой объем

 int х; // данных, поэтому передача

 … // по значению

// была бы неэффективной

public:

 virtual void operator(const T& val) const; // Виртуальная функция.

 … // создает проблему

}; // отсечения

Мы выделяем все данные и виртуальные функции в класс реализации и создаем компактный, мономорфный класс, содержащий указатель на класс реализации:

template<typename T> //Новый класс реализации

class BPFCImpl { //для измененного BPFC.

private:

 Widget w; // Все данные, ранее находившиеся

 int х; // в BPFC, теперь размещаются

 … // в этом классе,

 virtual ~BPFCImpl; // В полиморфных классах нужен

// виртуальный деструктор,

 virtual void operator(const T& val) const;

 friend class BPFC<T>; // Разрешить BPFC доступ к данным

};

template<typename T>

class BPFC: // Компактная, мономорфная версия

 public unary_function<T, void> {

private:

 BPFCImpl<T>* pImpl; // Все данные BPFC

public:

 void operator(const T& val) const; // Функция не является

 { // виртуальной; вызов передается

plImpl->operator(val); // BPFCImpl

 }

};

Реализация

BFPC::operator
дает пример того, как должны строиться реализации всех виртуальных функций
BPFC
: они должны вызывать свои виртуальные «прототипы» из
BPFCImpl
. Полученный в результате класс функтора (
BPFC
) компактен и мономорфен, но при этом он предоставляет доступ к большому объему данных состояния и работает полиморфно.

Материал изложен довольно кратко, поскольку описанные базовые приемы хорошо известны в кругах C++. В книге «Effective C++» этой теме посвящен совет 34. В книге «Приемы объектно-ориентированного проектирования» [6] соответствующая методика называется «паттерн Bridge». Саттер в своей книге «Exceptional C++» [8] использует термин «идиома

Pimpl
».

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

Герой

Бубела Олег Николаевич
4. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Герой

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

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

Гладиаторы

Трофимов Ерофей
Фантастика:
постапокалипсис
7.86
рейтинг книги
Гладиаторы

Первый среди равных

Бор Жорж
1. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных

Князь Целитель 4

Ткачев Андрей Юрьевич
4. Князь Целитель
Фантастика:
боевая фантастика
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Князь Целитель 4

Газлайтер. Том 25

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

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

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

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

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

Последний Паладин. Том 13

Саваровский Роман
13. Путь Паладина
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 13

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Выйду замуж за спасателя

Рам Янка
1. Спасатели
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Выйду замуж за спасателя

Газлайтер. Том 26

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

Бродяга. Книга вторая

Первухин Андрей Евгеньевич
2. Бродяга
Фантастика:
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Бродяга. Книга вторая

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

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