最近做了一个线程类,发现需要用用到重载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的话才会被覆盖