Роль слабого_птр в общем_птр

Я понимаю, как работает shared_ptr, за исключением роли слабого_птр. Я понимаю, что там можно обнаружить циклические ссылки, когда счетчик ссылок не равен нулю, но кроме этого, я не совсем понимаю, как именно это происходит. Что оно делает?

3

Решение

Смотрите также: Когда полезен std :: weak_ptr? почему и Как работает weak_ptr? на сколько.

Я приведу пример того, как я видел, как он использовался, хотя пример кода, который я написал, немного запутан, так что потерпите меня:

#include <vector>
#include <memory>
#include <ostream>

int main()
{
// Fill container with values 1-50. This container OWNS these values.
std::vector<std::shared_ptr<int>> owning_container;
for(int i = 1; i <= 50; ++i)
{
owning_container.emplace_back(std::make_shared<int>(i));
}

// Create a sepearate container that references all owned values that are multiples of 5.
std::vector<std::weak_ptr<int>> referencing_container;
for(std::shared_ptr<int> const& i : owning_container)
{
if((*i) % 5 == 0)
{
// Make weak_ptr that references shared_ptr
referencing_container.emplace_back(i);
}
}

// Go through the owned values and delete all that are multiples of 10.
for(auto it = owning_container.begin(); it != owning_container.end();)
{
std::shared_ptr<int> const& i = *it;
if(*i % 10 == 0)
{
it = owning_container.erase(it);
}
else
{
++it;
}
}

// Now go through the referencing container and print out all values.
// If we were dealing with raw pointers in both containers here we would access deleted memory,
//   since some of the the actual resources (in owning_container) that referencing_container
//   references have been removed.
for(std::weak_ptr<int> const& i_ref : referencing_container)
{
// Check if the shared resource still exists before using it (purpose of weak_ptr)
std::shared_ptr<int> i = i_ref.lock();
if(i)
{
std::cout << *i << std::endl;
}
}

return 0;
}

Здесь у нас есть контейнер, который содержит некоторый общий ресурс — в данном случае, int — (shared_ptr), что другой контейнер должен ссылаться (weak_ptr). Ссылка не является владельцем ресурса, ему нужно только иметь доступ к нему. если он существует. Чтобы сказать, если ресурс, на который ссылаются, все еще жив, мы конвертируем weak_ptr к shared_ptr с помощью weak_ptr::lock(), Те ресурсы, которые еще существуют, будут иметь действительный shared_ptr вернулся lock(), Те, которые больше не существуют, возвращают ноль shared_ptr, shared_ptr имеет operator bool() что мы можем использовать, чтобы проверить, является ли он нулевым или нет, прежде чем пытаться его использовать.

Менее запутанный сценарий может быть, если вы делаете игру, в которой каждый объект в игре представлен game_object, Скажем, у вас есть какая-то логика поиска врага, которая требует цели game_object искать. Используя вышесказанное, вы можете удержать врага на weak_ptr<game_object>, Это не владеет этим game_object, Если что-то еще убивает его цель, его цель должна умереть; не зависать в каком-то подвешенном состоянии, которое случится, если враг shared_ptr вместо. Таким образом, если цель противника все еще жива (что можно проверить, заблокировав weak_ptr), он может выполнять логику поиска; в противном случае он может найти новую цель. «Владелец» game_object может быть какой-то game_world класс — это будет иметь контейнер shared_ptr<game_object>, Когда врагу нужна новая цель, он может искать в этом контейнере и создавать свои weak_ptr от game_world«s shared_ptr,

3

Другие решения

Слабые указатели не претендуют на владение ресурсом, а только ссылаются на него. Таким образом, они не позволяют вам работать с ресурсом каким-либо образом, кроме повторного заявления о праве собственности (с weak_ptr::lock() метод). ИМХО, наиболее частыми ситуациями в реальной жизни, когда такое поведение является желанием, являются циклические зависимости и (реже) кэширование.

Циклические зависимости, создаваемые только с помощью общих указателей, де-факто являются утечками памяти, потому что количество взаимных ссылок указателей никогда не будет меньше 1: если ничто не владеет A, то B по-прежнему имеет, и наоборот. Слабый указатель не «обнаруживает» эту ситуацию. Это просто не пускает неприятности, просто разрывая петлю собственности. Вы все еще можете «соединить концы цепи», заблокировав слабый указатель, но ни один из общих указателей, которые вы можете получить через слабый, не будет сохранен.

Проблема с кешированием заключается в том, что кеш, как правило, не должен влиять на время жизни кэшируемого содержимого, это не является обязанностью кеша. Но если в кеше будут храниться общие указатели, вы не сможете завершить время жизни кэшированного объекта, не обращаясь к кешу, что часто неудобно.

2

По вопросам рекламы [email protected]