Когда объект имеет член-указатель, указатель может указывать на часть памяти, которая не принадлежит объекту. Таким образом, он может быть освобожден без информирования объекта и вызвать висячий указатель (и многочисленные головные боли для отладки). Например, допустим, у меня есть объект типа ClassHasPointer , который имеет переменную-член m_memberPtr типа AnotherClass *.
class ClassHasPointer
{
public:
void setMember(AnotherClass* anotherObj) { m_memberPtr = anotherObj; }
AnotherClass* getMember() { return m_memberPtr; }
private:
AnotherClass* m_memberPtr = nullptr;
}
Теперь предположим, что у меня есть объект AnotherClass с именем anotherObj , который я определил и использовал в другом месте программы. Теперь я решаю инициализировать объект ClassHasPointer :
ClassHasPointer A;
A.setMember(&anotherObj); // m_memberPtr points to anotherObj
Теперь, если anotherObj выходит из области видимости или освобождается в любой части программы, m_memberPtr указывает на мусор, поэтому это висячий указатель:
AnotherClass* aBadPtr = A.getMember(); // anotherObj was destroyed, dangling pointer!
Мы склонны часто использовать указатели в качестве переменных-членов в классах. Я думаю, что каждый раз, когда мы делаем это, мы предупреждаем, что класс может не владеть данными, на которые он указывает. Мои вопросы: как мы можем гарантировать, что у нас нет доступа к данным, пока они освобождены, без необходимости ненужного копирования данных, на которые они указывают? Что еще более важно, в целом, каковы хорошие практики / рекомендации / шаблоны проектирования, чтобы избежать этой ловушки?
РЕДАКТИРОВАТЬ: Я знаю, что мы можем использовать умные указатели, такие как std::shared_ptr
, но это может использоваться, только если в куче был определен другой объект (например, AnotherClass* anotherObj = new AnotherClass()
). Что если это не тот случай, и я не могу это изменить? Есть ли другие способы обойти проблему с висящими указателями?