Перейти к основному содержимому
Модуль 7 · Урок 2 из 216/18 в курсе~12 min
Уроки модуля (2/2)

std::weak_ptr

Хотя std::shared_ptr чрезвычайно полезен, использование исключительно совместного владения может привести к проблеме, известной как циклическая ссылка (или циклическая зависимость).

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

Что такое std::weak_ptr

Чтобы разорвать циклы владения, стандартная библиотека предлагает std::weak_ptr. Это интеллектуальный указатель, который наблюдает за объектом, управляемым shared_ptr, но без увеличения счетчика ссылок.

Он не владеет ресурсом напрямую, поэтому не предотвращает его уничтожение.

C++
#include <memory>

std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Does not increment reference count!

Проверка и доступ к ресурсу

Поскольку weak_ptr не владеет ресурсом, ресурс может быть освобожден в любое время (когда все связанные экземпляры shared_ptr выходят за пределы области действия).

Чтобы использовать наблюдаемый ресурс, мы должны:

  1. Проверьте, действителен ли он, с помощью expired().
  2. Временно преобразуйте weak_ptr в shared_ptr с помощью метода lock(). Если ресурс все еще активен, lock() возвращает действительный shared_ptr, в противном случае он возвращает нулевой указатель (nullptr).
C++
if (!weak.expired()) {
    // lock() creates a temporary shared_ptr to ensure safe access
    if (std::shared_ptr<int> sharedAccess = weak.lock()) {
        std::cout << *sharedAccess << std::endl;
    }
} else {
    std::cout << "Resource deallocated!" << std::endl;
}

Попробуйте сами

Упражнение#cpp.m7.l2.e1
Попыток: 0Загрузка…

Объявите std::weak_ptr<int> с именем wPtr, инициализированный из sPtr. Затем распечатайте логический результат, возвращенный wPtr.expired(), используя std::cout.

Загрузка редактора…
Показать подсказку

Объявите `weak_ptr`, указывающий тот же универсальный тип `<int>`, и назначьте ему `sPtr` непосредственно.

Решение доступно после 3 попыток

Упражнение#cpp.m7.l2.e2
Попыток: 0Загрузка…

Используйте метод lock() для wPtr, чтобы получить временный общий_ptr. Если операция завершилась успешно (указатель не равен нулю), выведите разыменованное значение.

Загрузка редактора…
Показать подсказку

Инициализируйте переменную внутри блока if, вызвав wPtr.lock(), затем распечатайте ресурс, разыменовав его звездочкой `*`.

Решение доступно после 3 попыток