Effective STL 总结

7.当使用new的指针容器时,记得在销毁容器前delete那些指针

当容器容纳的是指向通过new分配的对象的指针时,当指针容器被销毁时,不会销毁里面的指针,故会造成内存泄漏

class Widget
{
public:
private:
}; 
void doSomething()
{ 
	vector<Widget *> vwp;
 	for (int i = 0; i < size; ++i)
 	{        
		vwp.push_back(new Widget)
	}
}//如果直接退出会引起资源泄露 
 //解决方法1,函数中添加循环。
 //缺点:这段代码不是异常安全的,如果在向vwp中填充指针和从中删除指针
 //的过程中有异常抛出的话,同样有资源泄露
void doSomething()
{ 
	vector<Widget *> vwp; 
	for (int i = 0; i < size; ++i)  
	{
		vwp.push_back(new Widget);  
	}
	 for (vector<Widget*>::iterator i = vwp.begin(); i != vwp.end(); ++i)  
	{
		delete *i;
	}
}
//解决方法2:将循环变成for_each,将delete变成一个函数对象。
//缺点:需要指定要删除的类型,本例中为
Widget template<typename T>struct DeleteObject: public unary_function<const T*, void> void operator()(const T* ptr) const{    
	delete ptr;
}; 
void doSomething()
{ 
	vector<Widget *> vwp; 
	for (int i = 0; i < size; ++i)  
	{
		vwp.push_back(new Widget); 
	}	
 	for_each(vwp.begin(), vwp.end(), DeleteObject<Widget>())}
  //这种方法存在的隐患是,如果里面写的是一个基类的对象,则会出现使用基类的指针删除派生类的对象
  //当基类没有虚析构函数,则出现不确定行为,如下
  class SpecialString : public string{...};//同标准的STL容器一样,string没有虚析构函数,而从没有虚析构函数的类进行公有继承是C++的一项重要禁忌 
  void doSomthing()
  {    
    	deque<SpecialString*> desp; 
    	 ...    
 //不确定的行为!通过基类的指针删除派生类对象,而基类又没有虚构函数,因为两个类很像,所以在使用过程中可能出错。    
   for_each(dssp.begin(), dssp.end(), DeleteObject<string>());
 }
 //对于这种情况的解决方法是:
 //解决方法3:通过让编译器推断出传给DeleteObject::opertator()的指针类型,需要做的是将模板化从DeleteObject移到它的operator()中
struct DeleteObject
{    
   template<typename T>    
   void operator()(const T* ptr) const   
    {        
    	delete ptr;    
    }
    };//这种方法舍弃了可配接的能力 ,调用方法是  
    void doSomthing()
    {    
    	deque<SpecialString*> desp;   
     ...    
     for_each(dssp.begin(), dssp.end(), DeleteObject()); 
      //编译器知道传给operator()的内容,确定的行为
    } 
//这种方法仍然不是异常安全的,如果SpecialString已经被创建而对for_each的调用还没有开始时有异常被抛出,则会有资源泄漏发生
 //解决这种方法是使用智能指针容器代替指针容器,这里的智能指针通常是指被引用计数的指针//STL本身没有引用计数形式的智能指针,可以使用Boost库中的shared_ptr,则例子应该改写为:  
 void doSomthing()
 {    
 	typedef boost::shared_ptr<Widget> SPW;  
   	vector<SPW> vwp;    
    	for (int i = 0; i < size; ++i)
    	{
      		 vwp.push_back(SPW(new Widget));
      	}   //从Widget*创建SPW,然后对它进行一次push_back,使用vwp;
  }//这里不会有Widget资源泄露,即使在上面的代码中有异常抛出
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值