<p><image l:href="#books.png"/>13.5. Классы, управляющие динамической памятью</p>

Некоторые классы должны резервировать переменный объем памяти во время выполнения. Такие классы зачастую способны (а если способны, то обычно обязаны) использовать библиотечный контейнер для хранения данных. Например, для хранения своих элементов класс StrBlob использует вектор.

Но эта стратегия срабатывает не для каждого класса; некоторые из них должны самостоятельно резервировать память. Обычно такие классы определяют собственные функции-члены управления копированием, чтобы управлять памятью, которую они резервируют.

В качестве примера реализуем упрощенную версию библиотечного класса vector. Кроме прочих упрощений, этот класс не будет шаблоном, он сможет хранить только строки. Поэтому назовем этот класс StrVec.

Проект класса StrVec

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

Подобную стратегию и будем использовать в классе StrVec. Для получения пустой памяти используем класс allocator (см. раздел 12.2.2). Поскольку резервируемая классом allocator память пуста, используем его функцию-член construct() для создания объектов в этом пространстве, когда необходимо добавить новый элемент. Точно так же при удалении элемента используем его функцию-член destroy().

У каждого объекта класса StrVec будет три указателя на пространство, используемое для хранения его элементов:

• указатель elements на первый элемент в зарезервированной памяти;

• указатель first_free на следующий элемент после фактически последнего;

• указатель cap на следующий элемент после конца зарезервированной памяти.

Значение этих указателей представлено на рис. 13.2.

Рис. 13.2. Стратегия резервирования памяти класса StrVec

Кроме этих указателей, класс StrVec будет иметь переменную-член alloc типа allocator для резервирования памяти, используемой классом StrVec. У класса также будет четыре вспомогательных функции.

• Функция alloc_n_copy() будет резервировать пространство и копировать заданный диапазон элементов.

• Функция free() будет удалять созданные элементы и освобождать пространство.

• Функция chk_n_alloc() будет гарантировать наличие достаточного места для добавления по крайней мере еще одного элемента в вектор StrVec. Если места для следующего элемента нет, то функция chk_n_alloc() вызовет функцию reallocate() для резервирования большего пространства.

• Функция reallocate() будет пересоздавать вектор StrVec, когда прежнее пространство окажется исчерпано.

Хотя основное внимание уделено реализации, определим также несколько членов из интерфейса класса vector.

Определение класса StrVec

Теперь, сделав набросок реализации, можно определить класс StrVec:

// упрощенная реализация стратегии резервирования памяти для подобного

// вектору класса

class StrVec {

public:

 StrVec(): // член allocator инициализируется по умолчанию

  elements(nullptr), first_free(nullptr), cap(nullptr) { }

 StrVec(const StrVec&);            // конструктор копий

 StrVec &operator=(const StrVec&); // присвоение копии

 ~StrVec();                        // деструктор

 void push_back(const std::string&); // копирует элемент

 size_t size() const { return first_free - elements; }

 size_t capacity() const { return cap - elements; }

 std::string *begin() const { return elements; }

 std::string *end() const { return first_free; }

 // ...

private:

 std::allocator alloc; // резервирует элементы

 // используется функциями, которые добавляют элементы в StrVec

 void chk_n_alloc()

  { if (size() == capacity()) reallocate(); }

Перейти на страницу:

Похожие книги