重载delete(operator delete)

最近做了一个线程类,发现需要用用到重载delete,所以就此研究了一下

先来看看代码

struct thread
{
    thread()
    {
        printf("thread() 1\n");
        std::thread st(
            [](thread *self)
            {
                int i=0;
                while(1)
                {
                    std::chrono::milliseconds dura(1000);
                    std::this_thread::sleep_for(dura);
                    if(self->exit)
                    {
                        printf("thread run %d\n",i);
                        return;
                    }
                    i++;
                    printf("thread run %d\n",i);
                }
            }
            ,
            this
        );
        st.detach();

    }
    virtual ~thread()
    {
        printf("~thread()\n");
    }

    int exit=0;
};


int main()
{
    thread *p = new thread;


    //test(10);
    printf("---------end----------\n");
    getch();
    return 0;
}

这里使用了c++11标准,不熟悉的同学就当作伪代码来看

class thread是一个线程类。new thread 的时候就建立好了线程

好了,线程建立起来了,你可以把exit成员赋值为1的时候就会线程退出

你可以在类里面加入一个叫做close()这样的方法,把exit设置为1 然后在线程return之前delete self就可以了

 

但是这样违背了new delete配对的原则,用new出来线程,close线程太不合适

最好是new 线程,delete线程

可是问题就来了,delete之后 exit已经不存在,线程就会访问非法内存地址导致程序崩溃

这是一个矛盾的问题,如果能解决delete的时候设置exit=1却不销毁掉内存就能解决该问题了

c++已经准备好这样的功能给你了

 

c++ 对delete 一个对象的时候 首先会调用析构函数,你可以把析构函数看成一个特殊的函数,在delete对象的时候会被调用(其实就是)

紧接着 c++会调用delete 销毁掉内存,所以你现在只需要重载该类的delete就可以了,重载delete里面不去做任何销毁内存的事情,这样 内存得以保留

在类里面修改~thread()和添加一个重载delete:

    virtual ~thread()
    {
        printf("~thread()\n");
        exit=1;
    }

    void operator delete(void *self)
    {
        //nothing todo
    }

 

然后再线程return之前调用 delete (void*)self;

这样 在你delete p;的时候,首先exit被复制1,然后因为重载了类的delete 所以内存没有被销毁掉,所以程序依然正常运行,当线程遇到exit=1的时候,程序在退出前释放掉内存空间

这样就解决了new 和 delete 匹配问题

为什么 在线程return之前调用的是delete (void*)self;呢?原因很简单,你现在要做的事情是释放内容,而不是调用类的析构函数(现在析构函数也重载了delete不去干任何事了)

还有,经过测试delete会被继承到派生类,如果派生类重新重载delete的话才会被覆盖

 

posted @ 2013-03-03 14:44  卡卡的Blog  阅读(1173)  评论(1编辑  收藏  举报