Могу ли я удалить объект, принадлежащий другому с обратным вызовом из объекта, который будет удален? - PullRequest
2 голосов
/ 30 июня 2011

У меня есть один класс (A), который знает, когда его следует удалить. Я полагаю, что объект не может непосредственно удалить себя (то есть вы не можете вызвать деструктор изнутри него), поэтому я использовал обратный вызов.

Вот псевдокод моего текущего решения:

class A {
  Owner* owner; // is set in constructor

  A(Owner* ow) : owner(ow) {}
  void willDeleteOurself() {
    owner->deleteObject();
  }
} 

class Owner {
  A* obj;

  Owner() { // e.g. constructor
    obj = new A(this);
  }

  void deleteObject() {
    delete obj;
  }
}

У меня есть объект класса Owner, которому принадлежит объект класса A. Теперь, в какой-то момент, obj «знает», что оно должно быть удалено, и происходит вызов willDeleteOurself(). Кажется, этот код работает.

Теперь мой вопрос таков: Это безопасный способ удаления obj?

Я обеспокоен тем, что когда метод deleteObject возвращает (достигает }), он возвращается к концу willDeleteOurself(), но объект, из которого был вызван этот метод, был уничтожен.

Безопасна ли эта конструкция, когда у меня больше нет операторов, ссылающихся на obj после вызова owner->deleteObject();?

Обновление

Спасибо за ответы. Я немного упростил здесь. У меня нет A* obj;, но бустер смартпоинт (один, а иногда и на карте) к объекту. Я думаю, что если я вызову delete this для обернутого объекта, smartpointer не распознает, что базовый объект удален. Это правильно?

Поскольку delete this (а также мой код выше) "опасен", есть ли более безопасный способ решения моей проблемы?

Ответы [ 2 ]

5 голосов
/ 30 июня 2011

Это на самом деле так же хорошо, как звонить delete this; в willDeleteYourself. Хорошо, если у вас нет доступа к членам после удаления.

4 голосов
/ 30 июня 2011

Объект не может непосредственно удалить себя

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

Я сделал это с некоторыми объектами, которые запускают и забывают инкапсулировать поток или таймер.На самом деле они не принадлежали какому-либо другому объекту, поэтому они могут создаваться динамически и просачиваться до тех пор, пока не завершат свою работу.Тогда они будут вызывать delete this; в качестве самой последней операции.

Добавление промежуточных шагов из точки, в которой вам нужно (или вы хотите) удалить объект, и сам код удаления будет только выполнятьвещи сложнее и сложнее поддерживать.Следующий код:

void willDeleteOurself() {
   delete this;
   // [1]
}

гораздо более явный и легко читаемый: с этого момента объект мертв, вы не можете его использовать, не добавляйте код в [1], потому что объектмертвый сейчас .Если, с другой стороны, вы замаскируете delete посредством обратного вызова, тогда другие могут увидеть код и не осознавать, что добавление кода в [1] опасно.

...