Перейти до основного вмісту
Модуль 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, щоб отримати тимчасовий shared_ptr. Якщо операція виконана успішно (вказівник не є нульовим), надрукуйте розіменоване значення.

Завантаження редактора…
Показати підказку

Ініціалізуйте змінну всередині блоку «if», викликавши «wPtr.lock()», а потім надрукуйте ресурс із розіменуванням із зірочкою «*».

Рішення доступне після 3 спроб