首先说说标题可能取得有些大,但是可以理解为编程过程中有效的防止写的代码中有内存泄漏。好了废话不多说了,首先看下面一段代码。
class Image class Voice class People People::People( const std::string& n,const int& a,const int& h,const std::stirng& imgFileName,const std::string& vFileName ) People::~People( ) |
上面代码粗略看似没有问题,但是有没有想到如果People构造函数出错(内存不足,无法分配内存)怎么办?其结果可以预见,就是一个异常抛出来。但是我们仔细想想此时如果已经构造了Image类对象,而在构造Voice类对象时抛出的错误,这个情况会怎么办?程序会因为异常而停止,后面代码不会执行,那么pImg指针所指向的内存就不会得到正确的释放,那么内存就泄漏了。情况如下面代码:
... People *p =NULL; try{ p=new People("test",20,170,".../images/image01.jpg","../voices/voice01.dat"); ... catch( ... ){ delete p; throw; } delete p; } |
仔细想想 new People("test",20,170,".../images/image01.jpg","../voices/voice01.dat")里,如果最后为Image分配的内存被丢失,因为new操作没有成功完成,程序不会p进行赋值操作。所以catch中是没有任何操作的,已被分配的内存就丢失了。
因为对象在构造中抛出异常后C++不负责清除对象,所以我们需要重新设计构造函数让它们在运到异常的时候自己能清除所占用的内存。
People::People( const std::string& n,const int& a,const int& h,const std::stirng& imgFileName,const std::string& vFileName ) :name(n),age(a),height(h),pImg(0),pVoi(0) { try { if(imgFileName != "") { pImg = new Image( imgFileName ) ; } if(vFileName != " ") { pVoi = new Voice ( vFileName ); } } catch( ...) { delete pImg ; delete pVoi; throw ; } |