, что произойдет, если вы выполните «delete this?» в функции-члене?

17

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

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

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

A::~A()
{
    delete pi;
}
    
задан zhanwu 12.08.2011 в 13:43
источник

5 ответов

35

Этот C ++ FAQ отвечает на это довольно красиво, повторяя здесь:

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

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

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

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

    
ответ дан Alok Save 12.08.2011 в 13:57
источник
3

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

    
ответ дан Puppy 12.08.2011 в 13:44
источник
1

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

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

    
ответ дан Oliver Charlesworth 12.08.2011 в 13:44
источник
0

Вы можете 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 унициализирован, что приводит к деструктору, пытающемуся удалить оборванный указатель.

    
ответ дан visitor 12.08.2011 в 13:54
источник
-1

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

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

  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;
  }
 };
    
ответ дан asad_nitp 14.12.2016 в 08:58
источник