Подтвердить что ты не робот

Безопасно ли "удалить это"?

В моих первоначальных базовых тестах это совершенно безопасно. Тем не менее, мне показалось, что попытка манипулировать this позже в функции, которая delete this может быть ошибкой во время выполнения. Это правда, и безопасно ли оно delete this? или существуют ли только определенные случаи, когда это безопасно?

4b9b3361

Ответ 1

delete this является законным и делает то, что вы ожидаете: он называет ваш деструктор класса и освобождает базовую память. После того, как delete this вернется, ваше значение указателя this не изменится, так что теперь он является оборванным указателем, который не должен быть разыменован. Это включает неявное разыменование с использованием переменных-членов класса.

Обычно он встречается в классах с подсчетом ссылок, когда значение ref-count уменьшается до 0, функция DecrementRefCount()/Release()/whatever member вызывает delete this.

delete this обычно считается очень плохой формой по многим причинам. Легко случайно получить доступ к переменным-членам после delete this. Код вызывающего абонента может не понимать, что ваш объект имеет самоуничтожение.

Кроме того, delete this является "запахом кода", что ваш код может не иметь симметричной стратегии для владения объектами (кто выделяет и удаляет). Объект не мог присвоить себя new, поэтому вызов delete this означает, что класс A выделяет объект, но класс B позже освобождает его [self].

Ответ 2

Безопасно удалять "this" до тех пор, пока это фактически последняя операция в методе. На самом деле это делают несколько API-интерфейсов профессионального уровня (см. Пример реализации ATL CComObject).

Единственная опасность заключается в попытке получить доступ к любым другим данным элемента после вызова "удалить это". Это, безусловно, небезопасно.

Ответ 3

но не делайте этого в деструкторе!

Ответ 4

Удалить это совершенно законно, как уже отмечали другие. Это опасно для еще одной причины, о которой еще не упоминалось - вы предполагаете, что объект был выделен в кучу. Это может быть трудно гарантировать, хотя в случае использования ссылок на подсчеты обычно не проблема.

Ответ 5

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

Один из способов сделать это - сделать как конструктор, так и деструктор приватным и обеспечить создание объекта с помощью функции класса factory, которая создает объект в куче и возвращает указатель на него. Класс factory может быть статической функцией-членом или функцией друга. Затем очистка может быть выполнена с помощью метода Delete() для объекта, который выполняет "delete this". COM-объекты в основном работают таким образом, за исключением того, что кроме того они ссылаются на ссылку "удалить это", когда счетчик ссылок уменьшается до нуля.

Ответ 6

Да. Это должно быть прекрасно. "This" - это просто указатель. Любой указатель сделает для удаления. Информация о том, как удалить объект, содержится в записях кучи. Вот как IUnknown:: Release() обычно реализуется в COM-объектах.

Ответ 7

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

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

Ответ 8

Прочитайте для аналогичного обсуждения. Ваше понимание верно в том, что оно действительно работает, оно необходимо и может быть опасным, поскольку после этого вы не можете получить доступ к нему.

Ответ 9

Юридическая информация Да Безопасный Нет

Ответ 10

Рекомендуется использовать плохую практику delete this.

Однако, если используется, необходимо учитывать следующие моменты:

1. Оператор delete работает только для объектов, выделенных с помощью оператора new. Если объект создан с помощью new, то мы можем сделать delete this, иначе поведение undefined.

class A {
   public:
    void fun(){
     delete this;
   }
  };

 int main(){
   /* Following is valid */
   A *ptr = new A;
   ptr->fun();
   ptr = NULL // make ptr NULL to make sure that things are not accessed using ptr. 


    /* And following is invalid: Undefined Behavior */
    A a;
    a.fun();

    return 0;
}

2. После выполнения delete this любой элемент удаленного объекта не должен быть доступен после удаления.

 class A {
   int x;
  public:
    A() {
      x = 0;
     }
     void fun() {
      delete this;

    /* Invalid: Undefined Behavior */
    cout<<x;
  }
 };

Ответ 11

Если вы наследуете базовый класс и удаляете его в функции базового класса, использование указателя производного класса приведет к сбою. Например:

class Base
{

    virtual void Release()
    {
        delete this;
    }

}

class Derived : public Base
{

    void Foo()
    {
        ...
    }

}

main()
{

    Base *ptrDerived = new Derived();
    ptrDerived->release();
    ptrDerived->Foo() //Crash

}