Как не указывать на освобожденную память (висячие указатели) в классах с указателями - PullRequest
0 голосов
/ 12 апреля 2020

Когда объект имеет член-указатель, указатель может указывать на часть памяти, которая не принадлежит объекту. Таким образом, он может быть освобожден без информирования объекта и вызвать висячий указатель (и многочисленные головные боли для отладки). Например, допустим, у меня есть объект типа 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()). Что если это не тот случай, и я не могу это изменить? Есть ли другие способы обойти проблему с висящими указателями?

1 Ответ

0 голосов
/ 12 апреля 2020

Если в стеке объявлен AnotherClass, вы не сможете избежать зависания ссылки при выходе из области видимости. А с динамическим распределением c лучше не использовать прямой доступ к памяти, а использовать «умные указатели», и использование std :: shared_ptr решит вашу проблему. Но если динамическое распределение c недопустимо, вы можете попытаться избежать указателей и оптимизировать копирование, используя семантику перемещения ( Что такое семантика перемещения? )

...