一、STL 算法相关头文件
标准模板库 STL 算法 都定义在 <algorithm> , <numeric> 和 <functional> 三个头文件中 ;
使用 STL 标准模板库 算法时 , 导入上述 3 个头文件 , 导入时根据需求导入即可 , 不必都导入 ;
#include <algorithm>
#include <numeric>
#include <functional>
- <algorithm> 头文件 是 3 个 STL 算法头文件中 包含算法最多的一个 , 包含常用的 : 比较算法、交换算法、查找算法、遍历算法、复制算法、修改算法、反转算法、排序算法、合并算法 等 算法 ;
- <numeric> 头文件 包含的算法较少 , 这些算法 主要是 在 序列 上面进行简单数学运算 的模板函数 , 如 : 在 序列 上 执行 加减乘除 操作 ;
- <functional> 头文件 中 只 定义了一些模板类 , 这些模板类的作用是 声明函数对象 ;
STL 标准模板库 提供了 实现算法 的 模板函数 , 借助这些 模板函数 , 只需要几行代码 , 即可实现相应算法的复杂功能 , 极大地提升了开发效率 和 程序的可维护性 ;
二、函数对象 / 仿函数 简介
1、函数对象 / 仿函数 博客回顾
在之前的博客 【C++】STL 容器 - set 集合容器 ⑤ ( 仿函数 functor 简介 | 仿函数 functor 调用 | 自定义类排序规则 - 仿函数 / 重载 < 运算符函数 ) 中 简单的介绍了 " 仿函数 " 概念 ;
在结构体中的 operator()
就是 重载 函数调用操作符 ()
函数 ; 在 C++ 语言中 struct 结构体 与 class 类是等同的 , struct 结构体中的成员就是类成员 ;
struct IntCompare {
bool operator()(const int& a, const int& b) const volatile {
return (a < b); // 降序排序
}
};
创建 仿函数类 的 函数对象 , 然后通过 函数对象 调用 仿函数类 中的 " 重载 函数调用操作符 ()
函数 " ;
// 创建 仿函数对象
IntCompare ic;
// 通过 仿函数对象 调用仿函数
bool b = ic(1, 2);
2、函数调用操作符
" 函数调用操作符 " 是一种用于 调用函数的符号 , 通常是一对圆括号 ()
;
在 C++ 语言中 , 函数调用操作符都扮演着重要的角色 ;
" 函数调用操作符 " 的 主要作用是 将 函数 与其 参数 联系起来 , 并执行函数的代码 ;
函数调用操作 :
- 首先 , 在调用函数之前 , 必须 先 定义函数 并 指定其 参数列表 ;
- 然后 , 使用 函数调用操作符 告诉编译器将这些参数传递给函数 , 并执行函数的代码 ;
- 最后 , 函数执行后 , 将函数的返回值可以被赋值给变量 , 或者 直接使用 ;
定义一个函数 fun :
void fun(){}
调用 fun 函数 , 其中 函数名 " fun " 后面的 括号 " () " 就是 函数调用操作符 ;
fun();
3、函数对象 / 仿函数 - 重写函数调用操作符的类
" 函数对象 " 是 重载 函数调用操作符 " () " 的 类 , 又称为 " 仿函数 " , 它们是 行为类似函数 的 对象 ;
" 函数对象 " 本质是 类对象 , 其表现出一个函数的特征 , 通过该对象可以调用函数 , 通过对象名(参数列表)
的方式 可以调用 重载 ()
运算符函数 , 如果没有 创建该 函数对象的 上下文 代码 , 完全可以 把 函数对象 看作一个普通函数 ;
函数对象 / 仿函数 可以看做 Java 中的接口类 , 匿名内部类 , Kotlin 中的 Lambda 表达式 , 可以作为 回调函数 使用 ;
代码示例 :
#include "iostream"
using namespace std;
#include <algorithm>
#include "functional"
//函数对象 类重载了()
template <typename T>
class PrintT{
public:
void operator()(T& t){
cout << t << endl;
}
};
int main() {
int a = 666;
// 创建函数对象
PrintT<int> obj;
// 通过函数方式 调用 函数对象
obj(a);
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
4、函数对象 与 普通函数区别
函数对象 其 本质 是 类对象 , 能突破 函数的 概念 , 该类对象中 有成员变量 , 可以存储临时状态数据 ;
函数对象 / 仿函数 : 英文名称 " Function Objects / Functors " ;
- 定义 : 函数对象 是 重载了 operator() 的类的对象 , 也可以是结构体 ; 这种 类 / 结构体 的 对象 可以像函数一样被调用 ;
- 状态保持 : 函数对象可以有自己的数据成员,因此它们可以保持状态。这意味着在连续调用中,它们可以记住之前调用的信息。
- 灵活性 : 由于 函数对象 是 类的实例对象 , 开发时可以 通过 继承 和 重载 来 修改 重载函数调用操作符函数 的行为 ;
- 效率 : 在某些情况下 , 使用函数对象可能 比使用普通函数更有效率 , 因为 编译器可以进行内联优化 ;
普通函数 : 英文名称 " Ordinary Functions " ;文章来源:https://www.toymoban.com/news/detail-795555.html
- 定义 : 普通函数 是 C++ 言 中的 重要组件 , 通过函数名后跟括号和参数列表来调用 ;
- 状态保持 : 普通函数 不保持状态 , 每次调用结束后 , 其内部的局部变量的声明周期都会结束 , 并自动回收栈内存 ;
- 灵活性 : 普通函数可以通过参数传递来定制行为 , 但 不能通过继承和重载来改变其行为 ;
- 效率 : 普通函数通常 没有额外的函数调用开销 , 但在某些情况下 , 编译器可能无法对它们进行内联优化 ;
5、函数对象 与 普通函数 使用场景
函数对象 与 普通函数 使用场景 :文章来源地址https://www.toymoban.com/news/detail-795555.html
- 函数对象 : 如果 调用 多个函数 , 每个函数需要保持各自的状态 , 此时需要使用 函数对象 ;
- 普通函数 : 如果只需要 执行 一个简单的 , 无状态的 , 一次性的 函数调用 操作 , 此时推荐使用 普通函数 ;
到了这里,关于【C++】STL 算法 ① ( STL 算法相关头文件 | 函数对象 / 仿函数 简介 | 函数调用操作符 | 重写函数调用操作符的类 | 函数对象 与 普通函数区别 )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!