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

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

Жанры

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

 find(vw.begin,vw.end.bestWidget) // как у bestWidget

записывается в следующем виде:

class Widget{...};

typedef vector<Widget> WidgetContaner;

typedef WidgetContainer:iterator WCIterator;

WidgetContaner vw;

Widget bestWidget;

WCIterator i = find(vw.begin.vw.end,bestWidget);

Подобная запись

значительно упрощает изменение типа контейнера, что особенно удобно, когда изменение сводится к простому добавлению нестандартного распределителя памяти (такое изменение не влияет на правила недействительности итераторов/указателей/ссылок).

class Widget{...};

template<typename T> // В совете 10 объясняется, почему

SpecialAllocator{...}; // необходимо использовать шаблон

typedef vector<Widget, SpecialAllocator<Widget> WidgetContainer;

typedef WidgetContainer::iterator WCIterator;

WidgetContainer vw;// Работает

Widget bestWidget;

WCIterator i=find(vw.begin.vw.end.bestWidget); // Работает

Даже если вас не интересуют аспекты

typedef
, связанные с инкапсуляцией, вы наверняка оцените экономию времени. Предположим, у вас имеется объект типа

map<string,

 vector<Widget>::iterator,

 CIStringCompare> // CIStringCompare - сравнение строк

// без учета регистра: см. совет 19

и вы хотите перебрать элементы множества при помощи

const_iterator
. Захочется ли вам вводить строку

map<string.vector<Widget>::iterator, CIStringCompare>::const_iterator

больше одного раза? После непродолжительной работы в STL вы поймете, что

typedef
— ваш друг.

Typedef
всего лишь определяет синоним для другого типа, поэтому инкапсуляция производится исключительно на лексическом уровне. Она не помешает клиенту сделать то, что он мог сделать ранее (и не позволит сделать то, что было ранее недоступно). Если вы захотите ограничить зависимость клиента от выбранного типа контейнера, вам понадобятся более серьезные средства — классы.

Чтобы ограничить объем кода, требующего модификации при замене типа контейнера, скройте контейнер в классе и ограничьте объем информации, доступной через интерфейс класса. Например, если вам потребуется создать список клиентов, не используйте класс

list
напрямую, определите класс
CustomerList
и инкапсулируйте
list
в его закрытой части:

class CustomerList {

private:

 typedef list<Customer> CustomerContainer;

 typedef CustomerContainer::iterator CCIterator;

 CustomerContainer customers:

public: // Объем информации, доступной

 … // через этот интерфейс, ограничивается

};

На

первый взгляд происходящее выглядит глупо. Ведь список клиентов — это список, не правда ли? Вполне возможно. Но в будущем может оказаться, что возможность вставки-удаления в середине списка используется не так часто, как предполагалось вначале, зато нужно быстро выделить 20% клиентов с максимальным объемом сделок — эта задача просто создана для алгоритма
nthelement
(совет 31). Однако
nthelement
требует итератора произвольного доступа и не будет работать с контейнером
list
. В этой ситуации «список» лучше реализовать на базе
vector
или
deque
.

Рассматривая подобные изменения, необходимо проанализировать все функции класса

CustomerList
, а также всех «друзей» (
friend
) и посмотреть, как на них отразится это изменение (в отношении быстродействия, недействительности итераторов/указателей/ссылок и т. д.), но при грамотной инкапсуляции деталей реализации
CustomerList
это изменение практически не повлияет на клиентов
CustomerList
.

Совет 3. Реализуйте быстрое и корректное копирование объектов в контейнерах

В контейнерах хранятся объекты, но не те, которые вы им передаете. Более того, при получении объекта из контейнера вам предоставляется не тот объект, который находился в контейнере. При включении объекта (вызовом

insert, push_back
и т. д.) в контейнер заносится копия указанного объекта. При получении объекта из контейнера (например, вызовом
front
или
back
) вы также получаете копию. Копирование на входе, копирование на выходе — таковы правила STL.

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

vector, string
и
deque
существующие элементы контейнера обычно перемещаются (копируются) в памяти (советы 5 и 14). Алгоритмы сортировки (совет 31),
next_permutation
и
previous_permutation
;
remove
,
unique
и их родичи (совет 32);
rotate
и
reverse
— все эти операции приводят к копированию объектов. Да, копирование объектов действительно занимает очень важное место в STL.

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

class Widget{

public:

 Widget(const Widget&):// Копирующий конструктор

 Widget& operator=(const Widget&);// Копирующий оператор присваивания

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

Зубных дел мастер

Дроздов Анатолий Федорович
1. Зубных дел мастер
Фантастика:
научная фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Зубных дел мастер

Бывшие. Война в академии магии

Берг Александра
2. Измены
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Бывшие. Война в академии магии

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

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

Возвышение Меркурия. Книга 3

Кронос Александр
3. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 3

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

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

Хозяин Теней

Петров Максим Николаевич
1. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней

Опасная любовь командора

Муратова Ульяна
1. Проклятые луной
Фантастика:
фэнтези
5.00
рейтинг книги
Опасная любовь командора

Друд, или Человек в черном

Симмонс Дэн
Фантастика:
социально-философская фантастика
6.80
рейтинг книги
Друд, или Человек в черном

Волхв

Земляной Андрей Борисович
3. Волшебник
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Волхв

Мастер Разума VII

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

Всемирная энциклопедия афоризмов. Собрание мудрости всех народов и времен

Агеева Елена А.
Документальная литература:
публицистика
5.40
рейтинг книги
Всемирная энциклопедия афоризмов. Собрание мудрости всех народов и времен

Сумеречный Стрелок 5

Карелин Сергей Витальевич
5. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 5

Морской волк. 1-я Трилогия

Савин Владислав
1. Морской волк
Фантастика:
альтернативная история
8.71
рейтинг книги
Морской волк. 1-я Трилогия

Прогрессор поневоле

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