泛型算法

1 定义

可以用于不同类型的元素和多种容器类型的算法,实现了一些经典算法的公共接口。

2 相关头文件

在标准库中:

  • algorithm 头文件:定义了大多数算法
  • numeric 头文件:定义了一组数值泛型算法

3 概述

通常,算法遍历某一个范围(输入范围)内的元素,并对其中每个元素进行一些处理。

输入范围一般由两个迭代器指定,第一个指向要处理的第一个元素,第二个指向要处理的最后一个元素之后的位置。

迭代器的使用,令算法不依赖于容器,但算法依赖于元素类型的操作。
即访问元素可以通过迭代器解引用运算符实现,但算法通常会使用元素类型上的操作。

算法不会直接添加或删除元素。

4 向算法传递函数

4.1 谓词(predicate)

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

  • 一元谓词:只接受 1 个参数
  • 二元谓词:接受 2 个参数

谓词可以是函数指针,或者直接是函数名。

4.2 lambda 表达式

一个可调用的代码单元,可理解为一个未命名的内联函数。同函数类似,具有一个返回类型、一个参数列表和一个函数体。

lambda 表达式可以定义在函数内部。

lambda 表达式可以用作算法的谓词,并且借用捕获列表实现传递多于 2 个参数。

4.2.1 格式

[capture_list] (parameter_list) -> return_type {function_body}
  • capture_list:捕获列表,lambda 所在函数中定义的局部变量的列表,通常为空;
  • parameter_list:参数列表
  • return_type:返回类型,lambda 必须使用尾置返回
  • function_body:函数体

参数列表、返回类型可省略,但必须有捕获列表、函数体。


lambda 的形参不能有默认参数。——《C++ Primer》(第5版)

注:从 C++14 标准开始允许有默认参数。


如果 lambda 的函数包含任一 return 语句之外的内容,且未指定返回类型,则返回 void。——《C++ Primer》(第5版)

注:有编译器(如 MinGW64)不遵守此标准。


4.2.2 捕获列表

定义 lambda 时,可以认为是生成了一个未命名类,故向函数传递 lambda 可以看作是传递的参数是未命名类的未命名对象。

类似地,捕获变量是 lambda 的数据成员,在 lambda 定义时初始化。故一般被捕获的变量的值在 lambda 创建时拷贝,并且不随 lambda 所在函数的变量变化而变化,即为值捕获

要使被捕获的变量的值随 lambda 所在函数的变量变化而变化,应在捕获列表中使用变量的引用,即为引用捕获

尽量减少捕获变量,尽量避免捕获指针或引用。

可以不在捕获列表中列出所捕获的变量,由编译器根据 lambda 的函数体自行推断,即隐式捕获。但此时还应指示使用值捕获还是引用捕获。

捕获列表解释
[]空列表。lambda 不使用所在函数中的变量。
[identifier_list]捕获变量之间以逗号分隔,变量名前不加 & 则为值捕获,变量名前加 & 则为引用捕获。
[=, identifier_list]隐式捕获。默认为值捕获。= 后可以为空,或者列出使用引用捕获的变量(变量名前加 &)。
[&, identifier_list]隐式捕获。默认为引用捕获。& 后可以为空,或者列出使用值捕获的变量(变量名前不加 &)。

默认,lambda 不会改变值捕获的变量,若要改变,需在参数列表尾加上关键字 mutable,故可变 lambda 不能省略参数列表。

4.3 参数绑定

由于算法的谓词存在参数个数的限制,因此定义普通函数作谓词的方法受到限制,其参数个数有限。而 lambda 表达式因可以捕获所在函数的参数,所以在使用上更为灵活。

但 C++ 11 标准提供了标准库函数 bind,解决了定义普通函数做谓词的情况下的参数个数限制问题。bind 定义在头文件 functional 中,作为一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象。

4.3.1 格式

auto newCallable = bind(callable, arg_list);

bind 函数接受一个可调用对象 Callable 和一个参数列表 arg_list,返回一个新的可调用对象 newCallable

当调用 newCallable 时,newCallable 调用 callble,并将参数列表 arg_list 中的参数传递给 callable

4.3.2 参数列表

arg_list 包括两部分:

  • newCallable 接受的参数。这些参数传递给 newCallable 之后,又由 newCallable 传递给 callable 。在 arg_list 中应以占位符 _n 的形式出现,表示位于 newCallable 参数列表中的第 n 个参数。
  • 其他参数。

_n 定义在命名空间 std::placeholders 中。

默认,非占位符参数被被拷贝到 bind 返回的可调用对象中。若要以引用方式传递,需使用头文件functional 中定义的标准库 ref 函数(返回引用)或 cref 函数(返回 const 引用)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值