Класс weak_ptr (табл. 12.5) представляет интеллектуальный указатель, который не контролирует продолжительность существования объекта, на который он указывает. Он только указывает на объект, который контролирует указатель shared_ptr. Привязка указателя weak_ptr к указателю shared_ptr не изменяет счетчик ссылок этого указателя shared_ptr. Как только последний указатель shared_ptr на этот объект будет удален, удаляется и сам объект. Этот объект будет удален, даже если останется указатель weak_ptr на него. Имя weak_ptr отражает концепцию "слабого" совместного использования объекта.

Создаваемый указатель weak_ptr инициализируется из указателя shared_ptr:

auto p = make_shared(42);

weak_ptr wp(p); // wp слабо связан с p; счетчик ссылок p неизменен

Здесь указатели wp и p указывают на тот же объект. Поскольку совместное использование слабо, создание указателя wp не изменяет счетчик ссылок указателя p; это делает возможным удаление объекта, на который указывает указатель wp.

Таблица 12.5. Функции указателя weak_ptr

weak_ptr wОбнуляет указатель weak_ptr, способный указывать на объект типа T
weak_ptr w(sp)Указатель weak_ptr на тот же объект, что и указатель sp типа shared_ptr. Тип Т должен быть приводим к типу, на который указывает sp
w = pУказатель p может иметь тип shared_ptr или weak_ptr. После присвоения w разделяет собственность с указателем p
w.reset()Обнуляет указатель w
w.use_count()Возвращает количество указателей shared_ptr, разделяющих собственность с указателем w
w.expired()Возвращает значение true, когда функция w.use_count() должна возвратить нуль, и значение false в противном случае
w.lock()Возвращает нулевой указатель shared_ptr, если функция expired() должна возвратить значение true; в противном случае возвращает указатель shared_ptr на объект, на который указывает указатель w

Поскольку объект может больше не существовать, нельзя использовать указатель weak_ptr для непосредственного доступа к его объекту. Для этого следует вызвать функцию lock(). Она проверяет существование объекта, на который указывает указатель weak_ptr. Если это так, то функция lock() возвращает указатель shared_ptr на совместно используемый объект. Такой указатель гарантирует существование объекта, на который он указывает, по крайней мере, пока существует этот указатель shared_ptr. Рассмотрим пример:

if (shared_ptr np = wp.lock()) { // true, если np не нулевой

 // в if, np совместно использует свой объект с p

}

Внутренняя часть оператора if доступна только в случае истинности вызова функции lock(). В операторе if использование указателя np для доступа к объекту вполне безопасно.

Проверяемый класс указателя

Для того чтобы проиллюстрировать, насколько полезен указатель weak_ptr, определим вспомогательный класс указателя для нашего класса StrBlob. Класс указателя, назовем его StrBlobPtr, будет хранить указатель weak_ptr на переменную-член data класса StrBlob, которым он был инициализирован. Использование указателя weak_ptr не влияет на продолжительность существования вектора, на который указывает данный объект класса StrBlob. Но можно воспрепятствовать попытке доступа к вектору, которого больше не существует.

Класс StrBlobPtr будет иметь две переменные-члена: указатель wptr, который может быть либо нулевым, либо указателем на вектор в объекте класса StrBlob; и переменную curr, хранящую индекс элемента, который в настоящее время обозначает этот объект. Подобно вспомогательному классу класса StrBlob, у класса указателя есть функция-член check(), проверяющая безопасность обращения к значению StrBlobPtr:

// StrBlobPtr передает исключение при попытке доступа к

// несуществующему элементу

class StrBlobPtr {

 public:

 StrBlobPtr() : curr(0) { }

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

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