Что произойдет, если вы "удалите это"; в функции-члена?
Что произойдет, если функция-член попытается выполнить delete this;
, как в конструкторе следующего класса?
class A
{
public:
A(int);
~A();
int *pi;
}
A::A(int i)
{
delete this;
pi = new int(i);
}
A::~A()
{
delete pi;
}
Ответы
Ответ 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;
}
};