fill和fill_n函数的应用 / fill_n与generate_n的区别

fill函数的作用是:将一个区间的元素都赋予val值。函数参数:fill(first,last,val);//first为容器的首迭代器,last为容器的末迭代器,val为将要替换的值。

例题:给你n个数,然后输入一些操作:start,end,paint。表示从start到end都赋予paint的值,并输出每一次操作后的数组状态。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void print(int &elem){cout<<elem<<" ";}
int main()
{
    vector <int> V;
    int n,startpos,endpos,paint;
    cin>>n;
    V.resize(n);
    while(cin>>startpos>>endpos>>paint)
    {
            fill(V.begin()+startpos-1,V.begin()+endpos,paint);
        for_each(V.begin(),V.end(),print);
        cout<<endl;
    }
    return 0;
}


fill_n函数的作用是:给你一个起始点,然后再给你一个数值count和val。把从起始点开始依次赋予count个元素val的值。
注意: 不能在没有元素的空容器上调用fill_n函数
例题:给你n个数,然后输入一些操作:start,count,paint。表示从start开始连续填充count个数字,paint为填充的数值。
代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void print(int &elem){cout<<elem<<" ";}
int main()
{
    vector <int> V;
    int n,start,count,paint;
    cin>>n;
    V.resize(n);
    while(cin>>start>>count>>paint)
    {
        fill_n(V.begin()+start-1,count,paint);
        for_each(V.begin(),V.end(),print);
        cout<<endl;
    }
    return 0;
}
再发一下关于fill_n函数的例子:
// fill_n example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int main () {
  vector<int> myvector (8,10);        // myvector: 10 10 10 10 10 10 10 10

  fill_n (myvector.begin(),4,20);     // myvector: 20 20 20 20 10 10 10 10
  fill_n (myvector.begin()+3,3,33);   // myvector: 20 20 20 33 33 33 10 10

  cout << "myvector contains:";
  for (vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    cout << " " << *it;

  cout << endl;
 
  return 0;
}


-----------------------------------------------------------------------------------------------


void fill(ForwardIt first, ForwardIt last, const T& value);

void fill_n(OutputIt first, size n, const T& value);

功能:

        fill给迭代器范围[first, last)内元素均赋值为value。无返回值。

        fill_n将first指向范围内的前n个元素赋值为value。返回first+n(c++11)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template  < class  ForwardIterator,  class  T>
void  fill (ForwardIterator first, ForwardIterator last,  const  T& val)
{
   while  (first != last) {
     *first = val;
     ++first;
   }
}
     
template  < class  OutputIterator,  class  Size,  class  T>
OutputIterator fill_n (OutputIterator first, Size n,  const  T& val)
{
   while  (n>0) {
     *first = val;
     ++first; --n;
   }
   return  first;      // since C++11
}

void generate(first, last, Gen);

void generate_n(first, n, Gen);

功能:

       generate() 将调用函数对象/指针Gen()(无参数)后返回的结果依次赋值给[first, last)范围内的元素。

       generate_n() 将调用函数对象/指针Gen后返回的结果依次赋值给first指向范围内的前n个元素。

       注意:Gen不接收参数:Gen(),返回值转换为迭代器指向的元素的类型。

其声明和功能相当于:

1
2
3
4
5
6
7
8
template  < class  OutputIterator,  class  Size,  class  Generator>
void  generate_n ( OutputIterator first, Size n, Generator gen )
{
   while  (n>0) {
     *first = gen();
     ++first; --n;
   }
}

-------------------------------------------------------------------------------------

fill_n与generate_n的区别

July 3, 2008

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

list<int> l1;
fill_n(back_inserter(l1), 200, 1000);//back_inserter 是iterator适配器,它使得元素被插入到作为实参的某种容器的尾部,如vector等

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

 test.h

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>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());
这样程序就能顺利执行了


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值