3. Также реализуем функцию, которая выводит на экран информацию о слабом указателе, что позволит узнавать о его состоянии в разные моменты выполнения программы. Функция expired
weak_ptr
скажет о том, существует ли еще объект, на который он указывает, поскольку хранение слабого указателя на объект не продлевает его время жизни! Счетчик use_count
сообщает, сколько экземпляров типа shared_ptr
в данный момент указывают на наш объект:void weak_ptr_info(const weak_ptr
{
cout << "---------" << boolalpha
<< "\nexpired: " << p.expired()
<< "\nuse_count: " << p.use_count()
<< "\ncontent: ";
4. При желании получить доступ к самому объекту нужно вызвать функцию lock
null
. Следует это проверять, прежде чем получать доступ к объекту. if (const auto sp (p.lock()); sp) {
cout << sp->value << '\n';
} else {
cout << "
}
}
5. Создадим пустой слабый указатель в функции main
int main()
{
weak_ptr
weak_ptr_info(weak_foo);
6. В новой области видимости создадим новый общий указатель, содержащий только что созданный экземпляр класса Foo
1
, поскольку им владеет только один {
auto shared_foo (make_shared
weak_foo = shared_foo;
7. Вызовем функцию слабого указателя прежде, чем
Foo
должен быть мгновенно уничтожен, weak_ptr_info(weak_foo);
}
weak_ptr_info(weak_foo);
}
8. Компиляция и запуск программы дадут три результата работы функции weak_ptr_info
Foo
и может разыменовать его после Foo
в соответствии с нашими ожиданиями. После этого мы не можем получить содержимое экземпляра типа Foo
с помощью слабого указателя, а сам слабый указатель корректно распознает, что срок его действия истек.$ ./weak_ptr
---------
expired: true
use_count: 0
content:
---------
use_count: 1
expired: false
content: 1337
DTOR Foo 1337
---------
use_count: 0
content:
expired: true
Как это работает
Слабые указатели предоставляют способ указать на объект, поддерживаемый общими указателями, не увеличивая его счетчик использования. Да, необработанный указатель способен сделать то же самое, но не может сказать, является ли он висящим. Слабый указатель лишен этого недостатка!
Чтобы понять, как слабые указатели работают с общими, сразу рассмотрим рис. 8.3.
Принцип работы аналогичен тому, что приведен на рис. 8.2. В шаге 1 у нас имеются два общих указателя и слабый, указывающие на объект типа Foo
2
. Слабый указатель изменяет только 0
. В шаге 4 это приводит к тому, что объект Foo
удаляется, но блок управления Мы также можем сказать, что срок действия висящего слабого указателя
expired
класса weak_ptr
, он вернет булево значение. Если оно равно true
, то мы не можем разыменовать слабый указатель, поскольку он не указывает на объект.Чтобы разыменовать слабый указатель, нужно вызвать метод lock()
lock()
, то общий указатель, по сути, является null
.