Essential C++ 学习笔记:第三章 泛型编程风格(2)

目录

    • 3.5使用泛型算法
    • 3.6如何设计一个泛型算法
    • 3.7使用Map
    • 3.8使用set
    • 3.9如何使用Iterator Inserter
    • 3.10使用iostream Iterator


3.5使用泛型算法

  想要使用泛型算法,要包含对应的头文件

#include 

  具体范例参见书中附录B

3.6如何设计一个泛型算法

  拟定有一个新任务,用户会指定一个整形vector,我们需要返回一个新的vector,输出其中小于10的元素,比较简单的做法是定制化一个函数,令这个函数只能输出小于10的数字。但是这种函数的可扩展性几乎没有,所以要编写更普适的情况。将比较的值设定为一个输入的阈值,将比较操作设定为一个函数指针,将作用范围设定成一对iterator

int count_occurs(const vector<int> &vec, int val)
{
    vector<int>::const_iterator iter=vec.begin();
    int occurs_count=0;
    while((iter=find(iter,vec.end(),val))!=vec.end())
    {
        ++occurs_count;
        ++iter;
    }
    return occurs_count;
}

  当然一般情况下都会使用for循环来遍历容器,但是在使用iterator时,就会使用find_if()作用到容器上来取代for循环。find_if()允许支持函数指针输入外,还可以支持function object输入。function object可以看作对运算符的重载,但是将计算的类型抽象出来,STL实现定义了一组function object,分为算数运算、关系运算和逻辑运算三大类。
  function object的操作符一般都要求输入两个值,更一般的情况是将这个操作符转化成一元操作符,所以就需要将一个参数绑定(bind),这里使用了绑定适配器。将函数消除输出与输入类型,更加泛化的结果

template <typename InputIterator, typename OutputIterator,
            typename ElemType, typename Comp>
OutputIterator filter(InputIterator first, InputIterator last, 
OutputIterator at, const ElemType &val, Comp pred)
{
    while((first=find_if(first, last, bind2nd(pred, val)))!=last)
    {
        cout<<"found value: "<<*first<<endl;
        
        *at++=*first++;
    }
    return at;
}

  书中给出了一个练习,将sub_vec()改写为template function

3.7使用Map

  map被定义成一对数值,其中的key通常是个字符串,一般是索引符号,另一个数值是value

#include 
#include 
map<string,int>words;

//输入key/value的最简单方式是:
words["vermeer"] = 1;

//对于字数统计来言,我们可以采用以下方式:
string tword;
while(cin>>tword)
words[tword]++;

//其中表达式
//word[tword]
//会取出与tword相应的value。如果tword不在map内,他就会被放在map内,并获得默认值0。
//稍后出现的increment运算符会将其值递增1。

  查询map内是否存在某个key有三种办法。可以将key直接作为索引,但是当map中没有key时,map会自动补入key的索引,这样会改变map的结构,所以这种方法不值得推荐使用。第二种时mapfind()函数(与泛型函数find()不同,这里时map的成员函数)。

words.find("vermeer");

  如果key在其中,find()会返回一个iterator,指向key/value形成的pair,反之返回end()
  第三种是利用count()函数,调用和find()雷同,返回会返回在map中的个数,一般任何一个keymap中最多会有1份。

3.8使用set

  set是由一群key组合而成。如果我们想要知道一个value是否在某个集合里,就可以使用set

#include 
#include 
set<string> word_exclusion;

//为set添加单一元素
iset.insert(ival)//为set加入某个范围的元素
iset.insert(vec.begin(),vec.end())

3.9如何使用Iterator Inserter

  在上面的例子中,我们从一个容器中提取一个新的容器时需要新建一个新的容器。一般这个容器的大小都需要提前指定,但是实际上并不能这样。我们需要有一个空容器,然后根据得到的数据量来动态的扩展这个容器。

3.10使用iostream Iterator

  在现实应用的程序中,将结果输出到命令行是不现实的,所以很有必要将结果输出到输出文件中。

你可能感兴趣的:(Essential C++ 学习笔记:第三章 泛型编程风格(2))