std::weak_ptr
может быть создан из std::shared_ptr
, но у меня такой вопрос. weak_ptr
может вернуть информацию про умный указатель, точнее висячий он или нет.
Разве умные указатели не были созданы для того, чтобы предотвратить ситуации висячих указателей?
В чем смысл создавать std::shared_ptr
, чтобы с него делать еще один std::weak_ptr
, которым потом можно узнать или счетчик ссылок с блоке контроля умного указателя равен нулю?
Где это можно использовать? Как может std::weak_ptr
и информация которую он несет, быть полезной на практике?
std::weak_ptr
не является владельцем объекта, и призван решать проблему перекрестных ссылок.
Разберем такой код:
#include <iostream>
#include <memory>
#include <vector>
//Имеется класс компонента
struct Component:
public std::enable_shared_from_this<Component>
{ //Который содержит умные указатели на
std::vector<std::shared_ptr<Component>> children;//дочерние компоненты
std::shared_ptr<Component> parent;//и на родителя
void add(std::shared_ptr<Component> v)
{
children.push_back(std::move(v));
children.back()->parent = shared_from_this();
}
Component()
{
std::cout << "Component::Component()" << std::endl;
}
~Component()
{
std::cout << "Component::~Component()" << std::endl;
}
};
int main()
{
std::shared_ptr<Component> component1 = std::make_shared<Component>();
std::shared_ptr<Component> component2 = std::make_shared<Component>();
component1->add(std::move(component2));
}
Если запустить данный код, то увидим, что после выхода из main деструкторы объектов вызваны не были, т.е. объекты не уничтожились. Почему?
Всё дело в том, что объекты, которыми владеют std::shared_ptr
уничтожаются когда не остается владельцев (тех самых shared_ptr
). В нашем же коде, родительский компонент владеет дочерним, а дочерний компонент содержит shared_ptr
на родительский компонент, т.е. владеет родительским компонентом. Таким образом, они владеют друг другом, и не дают уничтожится друг другу. Это и есть перекрестные ссылки.
std::weak_ptr
является умным указателем, который не владеет объектом.
Если в вышеуказанном коде поменять тип parent на std::weak_ptr
, то родительский компонент теперь будет являться владельцем дочерних компонентов, а дочерние компоненты перестанут быть владельцами родительского. Соответственно, они не будут "держать друг друга за руки", и уничтожатся при выходе из main.
Иногда мы хотим чтобы объект удалился как можно быстрее, а не висел пока живы все его владельцы. Например когда объект владеет большим куском памяти, или каким-то системным ресурсом.
struct X {
char data[100500];
};
std::shared_ptr<X> sp(new X);
Мы можем закинуть ссылку на этот объект в много разных мест
AddTimer(3h, [wp = std::weak_ptr<X>(sp)]{
if (auto p = wp.lock()) {...};
});
и если мы не будем использовать weak_ptr
, то эти объекты будут висеть минимум по 3 часа.
(Тут надо отметить что мы также не можем использовать make_shared
т.к. тогда там будет выделен один большой блок памяти, который будет жить до последнего weak_ptr
.)
Также weak_ptr
позволяет бороться с утечками из-за циклических зависимостей.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Что правильнее передавать как аргумент функции(например в конструктор), если там эта строка будет просто скопирована?