Что произойдет, если вы удалите это в C ++

Возможный дубликат:
Можно использовать delete для удаления текущего объекта?

Я только что видел код, в котором они сделали delete this; в функции класса, я знаю, что это не лучший дизайн, но определено ли, что произойдет, скажем, что класс всегда является указателем откуда-то. Всегда ли он удаляется правильно?

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

class B
{
    void func() { A* a = new A; a->abort(); }
};

person hidayat    schedule 29.11.2010    source источник
comment
См. http://stackoverflow.com/questions/447379/what-is-the-use-of-delete-this/447531#447531   -  person icecrime    schedule 29.11.2010
comment
Связанные сообщения связаны, но не похожи на дубликаты.   -  person John Dibling    schedule 29.11.2010


Ответы (6)


Это совершенно законно в C ++ для delete this и на самом деле очень полезно для определенных шаблонов, таких как интеллектуальные указатели. Однако ответственность за это лежит на разработчике, чтобы убедиться, что никакие другие методы не вызываются или не хранятся в стеке для this, которые будут обращаться к данным экземпляра после удаления.

В C ++ FAQ Lite есть запись для этого, которую стоит прочитать

person JaredPar    schedule 29.11.2010
comment
В C ++ есть много вещей, которые совершенно легальны, но все же являются плохой идеей. - person Martin York; 29.11.2010

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

Классы Microsoft MFC широко используют delete this;, например, в классе CWnd (окно). Когда окно получает сообщение WM_DESTROY, класс-оболочка окна (которым является объект C ++) больше не нужен, поэтому он вызывает delete this; (я думаю, в PostNcDestroy(), где-то в этом роде). Это очень удобно с точки зрения пользователя фреймворка: вам просто нужно помнить, что существуют способы автоматического удаления объекта C ++, и будьте осторожны ближе к концу срока службы окна.

Я уверен, что есть много других реальных примеров, где delete this; является полезной парадигмой.

person AAT    schedule 29.11.2010

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

person MartinStettner    schedule 29.11.2010
comment
Это не единственное, о чем вам нужно заботиться. - person Edward Strange; 29.11.2010

да, его надо нормально удалить.

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

person Max    schedule 29.11.2010

В данном конкретном случае все в порядке, но подумайте, что произойдет, если a - автоматическая переменная:

void foo() {
    A a;
    a.abort(); // BOOM!
}
person Nikolai Fetissov    schedule 29.11.2010
comment
Что именно происходит, когда вы это делаете? - person Cameron; 29.11.2010
comment
Я считаю, что точное поведение не определено в языке, то есть это UB. Скорее всего, уровень распределителя будет утверждать, что адрес не находится в допустимом диапазоне. Попробуй :) - person Nikolai Fetissov; 29.11.2010
comment
Вы можете предотвратить это, сделав деструктор A защищенным. Тогда вы не сможете удалить указатель на A, кроме вызова его метода abort (), и не сможете создать его в стеке. - person CashCow; 29.11.2010
comment
Да, именно так это и делается. - person Nikolai Fetissov; 29.11.2010

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

person Raphael    schedule 29.11.2010
comment
Пока после оператора delete не используется никакая переменная-член, поведение четко определено. - person MartinStettner; 29.11.2010