是否允许删除这个;如果删除语句是将在该类实例上执行的最后一条语句?当然,我确定this指针所表示的对象是新创建的。

我在想这样的事情:

void SomeModule::doStuff()
{
    // in the controller, "this" object of SomeModule is the "current module"
    // now, if I want to switch over to a new Module, eg:

    controller->setWorkingModule(new OtherModule());

    // since the new "OtherModule" object will take the lead, 
    // I want to get rid of this "SomeModule" object:

    delete this;
}

我能这样做吗?


当前回答

这是允许的(只是在那之后不要使用对象),但我不会在实践中编写这样的代码。我认为delete this应该只出现在调用release或release的函数中,看起来像:void release() {ref——;If (ref<1);}。

其他回答

One of the reasons that C++ was designed was to make it easy to reuse code. In general, C++ should be written so that it works whether the class is instantiated on the heap, in an array, or on the stack. "Delete this" is a very bad coding practice because it will only work if a single instance is defined on the heap; and there had better not be another delete statement, which is typically used by most developers to clean up the heap. Doing this also assumes that no maintenance programmer in the future will cure a falsely perceived memory leak by adding a delete statement.

Even if you know in advance that your current plan is to only allocate a single instance on the heap, what if some happy-go-lucky developer comes along in the future and decides to create an instance on the stack? Or, what if he cuts and pastes certain portions of the class to a new class that he intends to use on the stack? When the code reaches "delete this" it will go off and delete it, but then when the object goes out of scope, it will call the destructor. The destructor will then try to delete it again and then you are hosed. In the past, doing something like this would screw up not only the program but the operating system and the computer would need to be rebooted. In any case, this is highly NOT recommended and should almost always be avoided. I would have to be desperate, seriously plastered, or really hate the company I worked for to write code that did this.

如果你害怕,有一个完全合法的破解方法:

void myclass::delete_me()
{
    std::unique_ptr<myclass> bye_bye(this);
}

我认为删除它是c++的惯用方法,我只是把它作为一种好奇来展示。

在某些情况下,这个构造实际上是有用的——您可以在抛出需要该对象成员数据的异常后删除该对象。对象在发生抛出之前一直有效。

void myclass::throw_error()
{
    std::unique_ptr<myclass> bye_bye(this);
    throw std::runtime_exception(this->error_msg);
}

注意:如果你使用的是c++ 11之前的编译器,你可以使用std::auto_ptr而不是std::unique_ptr,它会做同样的事情。

好吧,在组件对象模型(COM)中,删除这个结构可以是Release方法的一部分,当你想释放被获取的对象时,它会被调用:

void IMyInterface::Release()
{
    --instanceCount;
    if(instanceCount == 0)
        delete this;
}

这是一个老问题,但@Alexandre问“为什么有人想这样做?”,我想我可以提供一个示例用法,我今天下午正在考虑。

遗留代码。使用裸指针Obj* Obj,并在末尾使用delete Obj。

不幸的是,我有时需要,而不是经常,让对象活得更久。

我正在考虑使它成为一个引用计数智能指针。但会有很多代码要改变,如果我是使用ref_cnt_ptr<Obj>无处不在。如果你混合裸Obj*和ref_cnt_ptr,当最后一个ref_cnt_ptr消失时,你可以隐式删除对象,即使Obj*仍然存在。

因此,我正在考虑创建一个explicit_delete_ref_cnt_ptr。例如,一个引用计数指针,其中删除只在显式删除例程中完成。在现有代码知道对象的生命周期的地方使用它,以及在我的新代码中使用它,使对象的生存时间更长。

在操作explicit_delete_ref_cnt_ptr时增加或减少引用计数。

但当在explicit_delete_ref_cnt_ptr析构函数中看到引用计数为零时,则不释放。

仅当在显式删除类操作中看到引用计数为零时才释放。例如:

template<typename T> class explicit_delete_ref_cnt_ptr { 
 private: 
   T* ptr;
   int rc;
   ...
 public: 
   void delete_if_rc0() {
      if( this->ptr ) {
        this->rc--;
        if( this->rc == 0 ) {
           delete this->ptr;
        }
        this->ptr = 0;
      }
    }
 };

好吧,就像这样。引用计数指针类型不会自动删除rc'ed ptr析构函数中所指向的对象,这有点不寻常。但这似乎可以使混合裸指针和rc'ed指针更安全一些。

但到目前为止还不需要删除这个。

但后来我想到:如果被指向的对象,被指针,知道它被引用计数,例如,如果计数在对象内部(或在其他一些表中),那么例程delete_if_rc0可能是被指针对象的一个方法,而不是(智能)指针。

class Pointee { 
 private: 
   int rc;
   ...
 public: 
   void delete_if_rc0() {
        this->rc--;
        if( this->rc == 0 ) {
           delete this;
        }
      }
    }
 };

实际上,它根本不需要是一个成员方法,但可以是一个自由函数:

map<void*,int> keepalive_map;
template<typename T>
void delete_if_rc0(T*ptr) {
        void* tptr = (void*)ptr;
        if( keepalive_map[tptr] == 1 ) {
           delete ptr;
        }
};

(顺便说一句,我知道代码不太正确-如果我添加所有的细节,它变得不那么可读,所以我就这样留下它。)

你可以这样做。然而,你不能给它赋值。因此,你陈述这样做的原因,“我想改变观点”,似乎很有问题。在我看来,更好的方法是让持有视图的对象替换该视图。

当然,你使用的是RAII对象所以你根本不需要调用delete,对吧?