C++ Primer Chapter10 泛型算法

213 阅读4分钟

第十章 泛型算法

声明: 本文为《C++ Primer 中文版(第五版)》学习笔记。 原书更为详细,本文仅作学习交流使用,未经授权禁止转载。

在公众号【Jacen的技术笔记】,回复 C++,即可获得 两万字C++ Primer 要点整理PDF。

P336-P371

标准库并未给每个容器添加大量功能,而是提供了一组算法。这些算法是通用的,可以用于不同类型的容器和不同类型的元素。

10.1 概述

头文件:algorithm、numeric

算法不依赖于容器,但算法依赖于元素类型的操作。

10.2 初识泛型算法

(1)只读算法

accumulate 求和

equal 是否相等

(2)写容器元素的算法

算法不检查写操作

拷贝算法:copy

重排容器元素的算法:sort

::: tip

标准库函数对迭代器而不是容器进行操作。因此,算法不能直接添加或删除元素

:::

10.3 定制操作

标准库允许我们提供自己定义的操作来代替默认运算符。

(1)向算法传递函数

谓词:

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

标准库算法的谓词分为两类:

1、一元谓词:只接受单一参数。

2、二元谓词:接受两个参数。

bool isShorter(const string &s1, const string &s2)
{
		retrun s1.size() < s2.size();
}

sort(words.begin(), words.end(), isShorter);

排序算法:

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

(2)lambda表达式

lamba:

lambda表达式表示一个可调用的代码单元。一个lambda具有一个返回类型、一个参数列表和一个函数体。

[capture list](parameter list) -> return type {function body}
// capture list 捕获列表,lambda所在函数中定义的局部变量
// 捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和在它所在函数之外声明的名字
// lambda必须使用尾置返回来指定返回类型

(3)lambda捕获和返回

两种:值捕获、引用捕获

::: warnning

当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的。

一般的,应该尽量减少捕获的数据量,来避免潜在的问题。

如果可能,避免捕获指针或引用。

:::

隐式捕获

当混合使用隐式捕获和显式捕获时,捕获列表中的第一个元素必须是一个&或=。显式捕获的变量必须使用与隐式捕获不同的方式。

lambda捕获列表 P352

可变lambda:

若希望改变一个被捕获的变量的值,必须在参数列表首加上关键字mutable。

指定lambda返回类型:

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

(4)参数绑定

标准库bind函数:

auto newCallable = bind(callable, arg_list);
// 调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数

10.4 再探迭代器

插入迭代器、流迭代器、反向迭代器、移动迭代器

(1)插入迭代器

back_inserter:创建一个使用push_back的迭代器

front_inserter:创建一个使用push_front的迭代器

inserter:创建一个使用inserter的迭代器

(2)iostream迭代器

istream_iterator 读取输入流

ostream_iterator 向一个输出流写数据

istream_iterator操作:

istream-iterator操作
istream_iterator in(is);in从输入流is读取类型为T的值
istream_iterator end;读取类型为T的值得istream_iterator迭代器,表示尾后位置
in1 == in2 in1 != in2in1和in2必须读取相同类型。如果它们都是尾后迭代器,或绑定到相同的输入,则两者相等
*in返回从流中读取的值
in->mem与(*in).mem含义相同
++in, in++用>>从输入流读取下一个值

ostream_iterator操作:

ostream_iterator操作
ostream_iterator out(os);out将类型为T的值写到输出流os中
ostream_iterator out(os, d);out将类型为T的值写到输出流os中,每个值后面都输出一个d。d指向一个空字符串结尾的字符数组
out = val用<<将val写入到out所绑定的ostream中
*out, ++out, out++

(3)反向迭代器

反向迭代器就是在容器中从尾元素向首元素反向移动的迭代器。

10.5 泛型算法结构

迭代器类别
输入迭代器只读、不写;单遍扫描,只能递增
输出迭代器只写,不读;单遍扫描,只能递增
前向迭代器可读写;多遍扫描,只能递增
双向迭代器可读写,多遍扫描,可递增递减
随机访问迭代器可读写,多遍扫描,支持全部迭代器运算

10.6 特定容器算法

对于list、forward_list,应该优先使用成员函数的算法而不是通用算法。

术语

cref标准库函数:返回一个可拷贝的对象,其中保存了一个指向不可拷贝类型的const对象的引用