泛型算法

文章目录
  1. 1. 概述
    1. 1.1. 只读算法
    2. 1.2. 写容器元素算法
    3. 1.3. 重排元素的算法
  2. 2. 定制操作
    1. 2.1. 向算法传递函数
    2. 2.2. lambda表达式
    3. 2.3. lambda捕获和返回
    4. 2.4. 参数绑定
  3. 3. 再探迭代器
    1. 3.1. 插入迭代器
    2. 3.2. iostream迭代器
  4. 4. 泛型算法结构
    1. 4.1. 5种迭代器
    2. 4.2. 算法形参模式

主要内容:

  1. 概述
  2. 初始泛型算法
  3. 定制操作
  4. 再探迭代器
  5. 泛型算法结构
  6. 特定容器算法

概述

一般情况下,这些算法并不直接操作容器,而是遍历由两个迭代器指定的一个元素范围来进行操作。

算法永远不会执行容器操作:泛型算法本身不执行容器操作,他们只会运行于迭代器之上,执行迭代器的操作。这个特性带来一个非常惊人的编程假定:算法永远不会改变容器的大小。算法可能改变容器中元素的内容,可能在容器内移动元素,但永远不会添加或者删除元素。标准库定义定义了特殊的迭代器,插入迭代器。当算法操作这样的迭代器时迭代器可以完成向容器添加元素的效果,但算法永远不会做这种操作。

只读算法

find accumulate equal

除了少数算法外,标准库算法都对一个范围内的元素进行操作。我们将此元素的范围称为输入范围。接收输入范围的算法总是使用前两个参数来表示范围。两个参数分别表示第一个要处理的元素、尾元素之后位置的迭代器。

那些只接收一个单一迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长。

写容器元素算法

fill copy back_inserter replace_copy

重排元素的算法

定制操作

向算法传递函数

谓词:是一个可调用表达式,其返回结果是一个能用作条件的值。

一元谓词:接受单一参数
二元谓词:接受两个参数

stable_sort算法:维持相等元素的原有顺序

lambda表达式

find_if算法对输入序列中的每个元素调用这个谓词,它返回第一个使谓词返回非0的元素,如果不存在这样的元素,则返回尾迭代器。

可调用对象(cllable object)。对于一个对象或者一个表达式,如果可以对其使用调用运算符,则它为可调用对象。

可调用对象:

  1. 函数
  2. 函数指针
  3. 重载了函数调用运算符的类
  4. lambda表达式

可调用对象可以理解为是一个未命名的内联函数

一个lambda表达式具有一个返回类型、一个参数列表、一个函数体,单与函数不同,lambda表达式可以定义在函数内部,一个lambda表达式的一般形式

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

与普通函数不同,lambda表达式使用尾置返回指定返回类型。

可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体。如果忽略返回类型,lambda根据函数体重的代码推断出返回类型。

与普通函数不同,lambda不能有默认实参。

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

for_each算法接受一个可调用对象,并对输入序列中每个元素调用次对象。

捕获列表只用于局部非static变量,lambda可以直接使用局部static变量、它所在函数之外声明的名字。

lambda捕获和返回

当向一个函数传递一个lambda时,同时定义了一个类型和该类型的对象:类似的,当使用auto定义一个用lambda初始化变量时,定义了一个从lambda生产的类型的对象。

值捕获:与参数不同,被捕获的变量的值在lambda创建时拷贝。而不是调用时拷贝。

引用捕获:必须确保被引用的对象在lambda执行的时候是存在的。

隐式捕获: &搞事编译器采用引用捕获,=告诉编译器使用值捕获。混合使用隐式捕获和显示捕获时,捕获列表中的第一个元素必须是&或者=。

可变lambda:默认情况下,对于一个值被拷贝的变量,lambda不会改变其值,如果我们希望改变一个被捕获的变量的值。就必须在参数列表首加上关键字mutable。

参数绑定

bind标准函数 定义在functional中,可以将bind函数看做一个通用的函数适配器,他接受一个可调用对象,生成一个新的可调用对象来适应原来对象的参数。

bind的一般形式:

1
auto newCallable = bind(callable,arglist);

使用placeholders名字

_n定义在一个名为placeholders的命名空间。而这个命名空间定义在std命名空间中。

再探迭代器

  1. 插入迭代器
  2. 流迭代器
  3. 反向迭代器
  4. 移动迭代器

插入迭代器

接受一个容器,生成一个迭代器,他实现向容器添加元素。当我们通过一个插入迭代器进行赋值时,改迭代器调用容器操作来向给定容器指定的位置插入一个元素。

  1. back_inserter
  2. front_inserter
  3. inserter

iostream迭代器

泛型算法结构

5种迭代器

  1. 输入迭代器
  2. 输出迭代器
  3. 前向迭代器
  4. 双向迭代器
  5. 随机访问迭代器

算法形参模式