fill_n与generate_n的区别

我第一次看到这个函数,我就立马意识到这是初始化容器的好方法。比如

view plaincopy to clipboardprint?
01.list<int> l1;  
02. 
03.fill_n(back_inserter(l1), 200, 1000); 
list<int> l1;

fill_n(back_inserter(l1), 200, 1000);仅仅一行代码,就可以初始化200个元素,每个赋值为1000.多么方便啊。不过这种简单的类型我是没兴趣的。最重要的是可以初始化类,这就是我对其错误认识的开始。为了测试这个程序,我曾写下了如下代码:


view plaincopy to clipboardprint?
01.class TObj{  
02. 
03.public:  
04. 
05.    ~TObj(){cout<<"Deleting"<<endl;}  
06. 
07.};  
08. 
09.struct Dest_TObj{  
10. 
11.     template<class T>  T* operator()(T* p){  delete p;  return 0; }    
12. 
13.};  
14. 
15.int main(){  
16. 
17.    list<TObj*> tl;  
18. 
19.    fill_n(back_inserter(tl), 20, new TObj());  
20. 
21.    transform(tl.begin(),tl.end(),tl.begin(), Dest_TObj());  
22. 
23.    return 0;  
24. 
25.} 
class TObj{

public:

 ~TObj(){cout<<"Deleting"<<endl;}

};

struct Dest_TObj{

  template<class T>  T* operator()(T* p){  delete p;  return 0; } 

};

int main(){

 list<TObj*> tl;

 fill_n(back_inserter(tl), 20, new TObj());

 transform(tl.begin(),tl.end(),tl.begin(), Dest_TObj());

 return 0;

}在main函数中,第二行为tl初始化,20个元素,每个元素是一个指向TObj对象的指针,该指针指向一个新分配的TObj对象。然后在transform中对tl进行purge。如果不用这两个函数,我们只能用循环的方法: for( int i = 0; i < 20; ++i) tl.push_back(new TObj()); for( list<TObj*>::iterator iter = tl.begin(); iter!= tl.end();++iter) delete (*iter); 尽管看起来也行,但是总觉得比较原始,不是吗?

结果,当我满怀信心的运行程序,运行到transform时就崩溃了。我左看右看没发现问题。看看输出,有一个Deleting。那说明至少成功了一次,难道后面指针指错了?我把transform换成了上面的循环,结果也是运行了一次就崩溃了。看来问题在初始化的地方。 我把fill_n替换成上面的循环。程序欢快的跑完了。Shit,还有这事!

看来是fill_n有问题,我只能再回去仔细看fill_n的原型: template<class Out, class Size, class T>void fill_n(Out res, Size n, const T& val); 我终于注意到了最后一个参数,这是一个值参,fill_n只不过把每一个元素都用这个值进行赋值而已!因此,我希望初始化的20个TObj对象,实际上只有一个,所有的指针都指向这个对象。当第一个被delete之后,后面的就成了野指针。企图删除一块已经被释放了的内存块,当然结果是崩溃了。

如果要实现我需要的想法,只能使用generate_n。该函数和fill_n类似,只不过把最后一个参数换成了一个函数,调用该函数n次。 比如我有一个Create_TObj()的函数,返回一个新创建的TObj对象的话,我就可以把上面的代码改成:     generate_n(back_inserter(tl),20,Create_TObj()); 这样程序就能顺利执行了。

不幸的是,这个错误我是屡犯不改,终于不得已写下此文,希望能长点记性。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/leonhart/archive/2008/07/08/2626387.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值