10泛型算法

标准库并未给每个容器都添加大量功能,而是提供了一组标准算法,这些算法中的大多数都独立于任何特定的容器。这些算法是通用的(generic 或称为泛型的):它们可以用于不同类型的容器和不同类型的元素。

泛型算法(generic algorithm)之所以称为算法,是因为它们实现了一些经典算法的公共接口,如排序或搜索;称他们是泛型的,是因为它们可以用于不同类型的元素和多种容器类型。

三、lambda

调用运算符:如果可以对其使用调用运算符,则称一个对象是可以被调用的。 目前用过的可调用对象:函数和指针

[capture list](parameter list) ->return type {function body}

capture list(捕获列表)是一个lambda所在函数中定义的局部变量的列表(通常为空),其他与普通函数一样。lambda必须使用尾置返回来指定返回类型。

lambda不能有默认参数,所以lambda调用的实参数目必须与形参数目相等。

[](const string &a,const string b)
    {return a.sie() < b.size();}

 空捕获列表表明lambda不使用它所在函数中的任何局部变量。

stable_sort(words.begin(),words.end(), [](const string &a,const string b){return a.sie() < b.size();));

当stable_sort需要比较两个元素时,它就会调用lambda表达式。

lambda通过将局部变量包含在其捕获列表中,来指出将会使用这些变量。一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数中使用该变量。

[sz](const string &a)
    {return a.size() >= sz;}

auto wc = find_if(words.begin(),words.end(),[sz](const string &a){return a.size() >= sz});

 指向第一个长度大于给定参数sz的元素。如果不存在,则返回words.end()的一个拷贝。

例 1.接受两个int,返回它们的和。

auto sum = [](int a,int b) {return a + b};

2.捕获所在函数的int,并接受一个int参数。返回捕获int和int参数的和。

void add(int a){
    auto sum =[a](int b ) {return a + b };
}

 3.1 lambda捕获与返回

当向函数传递一个lambda时,同时定义了一个新类型与该类型的对象:传递的参数就是此编译器生成的类类型的未命名对象。

类似参数传递,变量的捕获方式也可以是值或者引用。

值捕获:在lambda创建时就拷贝v1的值,后面v1的值改变不影响值捕获的变量。 引用捕获:在lambda函数体内使用此变量时,实际上使用的是引用所绑定的对象。 当以引用方式捕获一个变量时,必须保证在lambda执行时变量时存在的。

混合使用显式捕获和隐式捕获:

&告诉编译器捕获引用方式; =告诉编译器采用值捕获方丝滑。

可变lambda

对于值捕获,参数列表加上:mutabl

auto f =[v1] () mutable {return ++v1};

一个引用捕获的变量能否修改取决于引用指向的变量时const 还是非const类型。

指定lambda返回类型

当需要为lambda指定返回类型时,必须使用尾置类型。

[](int i) -> int {if (i < 0)  return -i; else return i;}

四、迭代器

插入迭代器

 标准库算法为了保证通用性,并不直接操作容器,而是通过迭代器来访问容器元素,算法不具备直接向容器插入元素的能力,而插入器正式帮助算法实现向容器插入元素的能力。有三种类型,区别在于元素插入位置不同。

  • back_inserter
  1. 原理:创建一个使用push_back的迭代器。调用push_back.
  2. 功能:在容器的尾端插入元素。
  3. 限制:只有提供了push_back()成员函数的容器中,back_inserter才能派上用场。
  4. 适用:vector deque lis
  • front_inserter:
  1. 原理:创建一个使用push_front的迭代器。调用push_front.
  2. 功能:在容器前端插入元素
  3. 限制:只有提供了push_front()成员函数的容器中,form_Inserter才能派上用场。
  4. 适用:deque list
  • inserter
  1. 原理:创建一个使用insert的迭代器。此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。
  2. 功能:在容器的指定位置插入元素。
  3. 限制:只有提供了inset()成员函数的容器中,inserter才能派上用场,所有STL容器都提供了inset()函数。
  4. 适用:所有STL容器。

iostream迭代器

通过流迭代器,我们可以用泛型算法从流对象读取数据以及向其写入数据。
istream_iterator:读取输入流

ostream_iterator:向一个输出流写数据。

istream_iterator<int> in_iter(cin);//从cin读取int
istream_iterator<int>eof; //isteram尾后迭代器
while(in_iter != eof)
    vec.push_back(*in_iter++);

对于一个绑定到流的迭代器,一旦关联的流遇到文件尾或遇到IO错误,迭代器的值就与尾后迭代器相等。

ostream_iterator

ostream_iterator(T) out(os);    //out将类型为T的值写入到输出流os中
ostream_iterator(T) out(os,d)//out将类型为T值写入到输出流os中,每个值后面都输出一个d,d指向一个空字符结尾的字符数组。
void change(vector<int>&vec) {
    ostream_iterator<int> out_iter(cout, "danliu");
    for (auto e : vec)
        *out_iter++ = e; //赋值语句将e写入到cout
    cout << endl;
}

以下代码也能用来打印容器

    ostream_iterator<int>out_iter(cout," ");
    copy(vec.begin(),vec.end(),outiter);

五、泛型算法结构

算法要求的迭代器操作可以分为5个迭代器类别(iterator category),每个算法都会对它的每个迭代器参数指明需要提供哪类迭代器。

  • Input iterator(输入迭代器):只读,不写,单遍扫描,只能递增;
  • Output iterator(输出迭代器):只写,不读,单遍扫描,只能递增;
  • Forward iterator (前向迭代器):可读写,多遍扫描,只能递增;
  • Bidirectional iterator(双向迭代器):可读写,多遍扫描,可递增递减;
  • Random Access iterator(随机访问迭代器):可读写,多遍扫描,支持全部迭代器运算;
陈小洁的三只猫
原文地址:https://www.cnblogs.com/ccpang/p/11303839.html