第10章_泛型算法

概述

  • 标准库容器定义的操作集合惊人得小, 并未给每个容器添加大量功能, 而是提供了一组算法, 这些算法中的大多数都独立于任何特定的容器
  • 一般情况下, 这些算法并不直接操作容器, 而是遍历由两个迭代器指定的一个元素范围来操作
  • 算法永远不会改变底层容器的大小, 可能改变容器中保存的元素的值, 也可能在容器内移动元素, 但永远不会直接添加或删除元素

初始泛型算法

只读算法

写容器元素的算法

重排容器元素的算法

定制操作

想算法传递函数

lambda 表达式

可调用对象

  • 函数
  • 函数指针
  • 重载了函数调用运算符的类
  • lambda 表达式

lambda 捕获和返回

  • 当定义一个 lambda 时, 编译器生成一个与 lambda 对应的新的(未命名的)类类型.(当向一个函数传递了一个 lambda 时, 同时定义了一个新类型和该类型的一个对象: 传递的参数就是次编译器生成的类类型的未命名对象)
  • & 告诉编译器采用捕获引用方式, = 则表示采用值捕获方式

参数绑定

标准库 bind 函数

  • 可以将 bind 函数看作一个通用的函数适配器, 它接受一个可调用对象, 生成一个新的可调用对象来适应原对象的参数列表
    1
    2
    3
    4
    auto newCallable = std::bind(callable, arg_list);
    // newCallable 本身是一个可调用对象
    // arg_list 是一个逗号分隔符的参数列表, 对应给定的 callable 参数
    // 当调用 newCallable 时, newCallable 会调用 callable, 并传递给它 arg_list 中的参数

使用 placeholders 名字

1
2
3
4
5
6
7
8
9
std::placeholders::_n;
// 占位符, 表示 newCallable 的参数, 它们占据了传递给 newCallable 的参数的位置. 数值 n 表示生成的可调用对象中参数的位置: _1 为 newCallable 的第一个参数, _2 为第二个参数, 以此类推

void func(int a, int b) {
std::cout << a << ' ' << b << std::endl;
}

auto f = std::bind(func, std::placeholders::_2, std::placeholders::_1);
f(3, 4); // out: 4 3

绑定引用参数

  • 默认情况下, bind 的那些不是占位符的参数被拷贝到 bind 返回的可调用对象中
  • 如果希望传递给 bind 一个对象而不拷贝它, 就必须使用标准库 ref 函数(ref 返回一个对象, 包含给定的引用, 此对象是可以拷贝的; cref 生成一个保存 const 引用的类)

再探迭代器(没看)

插入迭代器

iostream 迭代器

反向迭代器

泛型算法结构(没看)

5 类迭代器

算法形参模式

算法命名规范

特定容器算法