} //
//
В этой версии функции use_factory() оператор return возвращает вызывающей стороне (см. раздел 6.3.2) копию указателя p. Копирование указателя shared_ptr добавляет единицу к счетчику ссылок этого объекта. Теперь, когда указатель p удаляется, останется другой владелец области памяти, на которую указывал указатель p. Класс shared_ptr гарантирует, что пока есть хоть один указатель shared_ptr на данную область памяти, она не будет освобождена.
Поскольку память не освобождается, пока не удаляется последний указатель shared_ptr, важно гарантировать, что ни одного указателя shared_ptr не остается после того, как необходимость в них отпадет. Если не удалить ненужный указатель shared_ptr, программа будет выполнятся правильно, но может впустую тратить память. Одна из возможностей оставить указатели shared_ptr после употребления — поместить их в контейнер, а затем переупорядочить его так, чтобы эти элементы оказались не нужны. Поэтому важно гарантировать удаление элементов с указателями shared_ptr, как только они больше не нужны.
shared_ptr помещаются в контейнер, но впоследствии будут использованы лишь некоторые из них, а не все, то следует не забыть самостоятельно удалить остальные элементы.
Обычно динамическую память используют в следующих случаях.
1. Неизвестно необходимое количество объектов.
2. Неизвестен точный тип необходимых объектов.
3. Нельзя разрешать совместное использование данных несколькими объектами.
Классы контейнеров — хороший пример классов, использующих динамическую память, как в первом случае. Примеры второго рассматриваются в главе 15. В данном разделе определяется класс, использующий динамическую память для того, чтобы позволить нескольким объектам совместно использовать те же данные.
Использованные до сих пор классы резервировали ресурсы, которые существовали, только пока существовал объект. Например, каждому вектору принадлежат его собственные элементы. При копировании вектора элементы исходного вектора копировались в независимые элементы другого:
vector
{ //
vector
v1 = v2; //
} //
//
Элементы вектора существуют, только пока существует сам вектор. Когда вектор удаляется, удаляются и его элементы.
Некоторые классы резервируют ресурсы, продолжительность существования которых не зависит от первоначального объекта. Например, необходимо определить класс Blob, содержащий коллекцию элементов. В отличие от контейнеров, объекты класса Blob должны быть копиями друг друга и совместно использовать те же элементы. Таким образом, при копировании объекта класса Blob элементы копии должны ссылаться на те же элементы, что и оригинал.
Обычно, когда два объекта совместно используют те же данные, они не удаляются при удалении одного из объектов:
Blob
{ //
Blob
b1 = b2; //
} //
//
В этом примере объекты b1 и b2 совместно используют те же элементы. Когда объект b2 выходит из области видимости, эти элементы должны остаться, поскольку объект b1 все еще использует их.
Основная причина использования динамической памяти в том, чтобы позволить нескольким объектам совместно использовать те же данные.
StrBlobВ конечном счете класс Blob будет реализован как шаблон, но это только в разделе 16.1.2, а пока определим его версию, способную манипулировать только строками. Поэтому назовем данную версию этого класса StrBlob.
Простейший способ реализации нового типа коллекции подразумевает использование одного из библиотечных контейнеров. Это позволит библиотечному типу управлять собственно хранением элементов. В данном случае для хранения элементов будет использован класс vector.