У меня есть объект, на который указывают многие указатели. Они часто пытаются получить доступ к данным. Однако в какой-то момент этот объект может быть уничтожен. Как мне эффективно обновить эти указатели, как только я уничтожу объект, чтобы они не указывали на нераспределенную память и не вызывали неопределенное поведение?
Моя идея заключалась в том, чтобы составить список указателей, которые необходимо обновить до nullptr. Это будет вызываться в деструкторе объекта. Ужасный беспорядок и много работы для каждой вещи, которая может быть освобождена.
Может быть, в этих умных указателях есть какая-то польза для таких случаев (никогда их не использовал). Как программисты C++ справляются с такими вещами?
Как насчет подсчета ссылок?





Вам просто нужно использовать std::shared_ptr и std::weak_ptr.
shared_ptr настолько умны, что вам не нужно их удалять, они будут удалены, когда на них больше никто не ссылается. Тогда любой weak_ptr, связанный с этим shared_ptr, будет как бы проинформирован, и нет риска, что он получит доступ к нераспределенной памяти.
Когда это потребуется, weak_ptr попытается подключиться к lock() и создать локальный shared_ptr. Если исходный shared_ptr был удален, lock() не сможет создать локальный shared_ptr, и вы будете уверены, что исходный указатель был удален.
// Example program
#include <iostream>
#include <assert.h>
#include <memory>
int main()
{
std::shared_ptr<int> pI( new int(3) );
std::weak_ptr<int> wI( pI );
{
// check if weak_ptr still "points" to some valid data:
std::shared_ptr<int> pICopy = wI.lock();
assert( pICopy != NULL );
std::cout << "pI still valid " << *pICopy << std::endl;
}
pI.reset(); // this is equivalent to regular delete with shared_ptr
{
// check if weak_ptr does not "point" to any valid data:
std::shared_ptr<int> pICopy = wI.lock();
assert( pICopy == NULL );
std::cout << "pI not valid anyore" << std::endl;
}
}
Это примерно то, что я хотел. Думаю, пришло время изучить новую систему указателей...
Ugly mess and a lot of work for every single thing that might be deallocated
Ну не делайте очистку в деструкторе. Сделайте отдельную функцию и вызовите ее в деструкторе. Вы можете вызвать эту общую функцию очистки из деструкторов других объектов.