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

Что произойдет, если вы "удалите это"; в функции-члена?

Что произойдет, если функция-член попытается выполнить delete this;, как в конструкторе следующего класса?

class A
{
public:
    A(int);
    ~A();
    int *pi;
}

A::A(int i)
{
    delete this;
    pi = new int(i);
}

A::~A()
{
    delete pi;
}
4b9b3361

Ответ 1

This С++ FAQ отвечает на это довольно хорошо, повторяя здесь:

До тех пор, пока вы будете осторожны, это нормально для объекта delete this.

Вот как я определяю "осторожно":

  • Вы должны быть абсолютно уверены в том, что этот объект был выделен через новый (а не новый [], ни место размещения new, ни локальный объект в стеке, ни глобальный, ни член другого объекта; простым обычным новым).
  • Вы должны быть абсолютно уверены, что ваша функция-член будет последней функцией-членом, вызываемой на этом объекте.
  • Вы должны быть абсолютно на 100% уверенно уверены, что остальная часть вашей функции-члена (после удаления этой строки) не касается какой-либо части этого объекта (включая вызов любых других функций-членов или касание любых элементов данных).
  • Вы должны быть абсолютно на 100% уверенно уверены, что никто даже не коснется этого указателя после удаления этой строки. Другими словами, вы не должны его проверять, сравнивать с другим указателем, сравнивать его с NULL, печатать его, бросать, делать с ним что-либо.

Вы нарушаете # 3, обращаясь к pi после delete this

Ответ 2

Плохие вещи. Вы можете delete this;, но, как правило, это очень плохая идея, и после этого вы не можете касаться каких-либо переменных-членов или функций-членов.

Ответ 3

В общем случае вызов delete this изнутри функции-члена хорошо определен, если он немного рискован.

Но это, вероятно, очень плохая идея, чтобы вызывать его из конструктора (я не знаю, если он четко определен). Зачем вам это делать?

Ответ 4

Вы можете delete this, но это предполагает, что экземпляр был создан с помощью new и что вы больше не получаете доступа к каким-либо членам экземпляра.

В вашем примере почти то же самое произойдет, если вы сделали

class A
{
public:
    A(int);
    int *pi;
};

A::A(int i)
{
    pi = new int(i);
}

int main()
{
   A* p = new A(10);
   delete p;
   p->pi = new int; //bad stuff

//or
   A a(20);
   delete &a;  //bad stuff
   a.pi = new int; //more bad stuff
}

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

Ответ 5

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

1) оператор delete работает только для объектов, выделенных с использованием нового оператора. Если объект создается с помощью new, мы можем удалить его, иначе поведение 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) После удаления этого действия любой элемент удаленного объекта не должен быть доступен после удаления.

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

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