удалить это ? Что это делает? - PullRequest
2 голосов
/ 28 августа 2011

Учитывая следующее:

#include <iostream>
using namespace std;

class A
{
public:
    void func() {delete this;}
    A() : x(5) {cout << "ctor A" << endl;}
    ~A() {cout << "dtor A" << endl;}
    int x;
};

int main() {
    A a;
    cout << "The X value: " << a.x << endl;
    a.func();  // calling 'delete this' ->going to the dtor #1
    cout << "The X value: " << a.x << endl;
    return 0;  
}

вывод:

ctor A
The X value: 5
dtor A
The X value: 5
dtor A

Есть ли у * 1007 какие-либо серьезные последствия?

Ответы [ 5 ]

5 голосов
/ 28 августа 2011

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

Можно написать код, где "удалить это;" было бы хорошо, хотя. Но я не могу вспомнить, чтобы когда-либо делал это. Постарайся избежать этого. Старайтесь избегать вызова delete вручную (независимо от того, использовали ли вы новый или нет), передав эту ответственность другому объекту (например, интеллектуальному указателю).

3 голосов
/ 28 августа 2011

Оператор delete вызывает деструктор объекта, а затем освобождает базовую память, используемую объектом. Память должна выделена оператором new. В delete this удаленный объект является просто текущим объектом. В конструкции нет ничего особенного, это просто C ++.

В вашем примере память из стека, и, таким образом, вы входите в область неопределенного поведения (поскольку вы вызываете оператор delete для объекта, который не был выделен с помощью оператора new).

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

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

3 голосов
/ 28 августа 2011

Я посмотрю в прошлом, что вы вызываете delete для объекта, выделенного из стека, и изучу использование delete this в целом.

Существует школа мысли, которая говорит: «Этоне хорошая идея".Тем не менее, я видел, как оно использовалось несколько раз с реализациями объектов с подсчетом ссылок.

В COM каркас требует, чтобы все объекты создавались фабричным методом, а затем снова вызывались при вызове «Release».

  class MyRefCountedObject : public IUnknown
  {
      private:
           // Making the constructor and destructor private
           // so that the object can only be allocated as a pointer

           MyRefCountedObject() {}

           ~MyRefCountedObject() {}

           MyRefCountedObject(const MyRefCountedObject& mrco) {}

            int _refCount;
      public:
           static MyRefCountedObject* CreateInstance()
           {
                MyRefCountedObject* pObject = new MyRefCountedObject();
                pObject->_refCount = 1;
                return pObject;
           }

           void Release()
           {
                if(--_refCount == 0)
                {
                    delete this;
                }
           };
           void AddRef()
           {
               ++_refCount;
           }
  }

Обратите внимание - это не полная реализация, а просто представление о логике.Но, сделав конструктор частным, я могу гарантировать , что это когда-либо будет размещено только в куче.

2 голосов
/ 28 августа 2011

C ++ FAQ Lite: «Законно ли (и морально) ли функция-член сказать« удалить это »?»

Тем не менее, вам редко следует пользоваться, если вообще когда-либодля этого в правильно организованном коде.

0 голосов
/ 28 августа 2011

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

...