跳到主要内容
版本:Next

functional

<functional> 提供函数对象(仿函数)、函数适配器和常用谓词工具,是 STL 算法可配置性的关键部分。

在 C++98 时代,还没有 lambda,很多“把行为当参数传递”的写法依赖 <functional>

头文件与核心概念

#include <functional>

常见概念:

  1. 函数对象:实现了 operator() 的对象。
  2. 谓词:返回 bool 的函数对象,常用于算法筛选。
  3. 适配器:把已有函数对象做“绑定、组合、取反”等处理。

常见函数对象

<functional> 内置了大量基本运算函数对象:

类型作用
std::plus<T>加法
std::minus<T>减法
std::multiplies<T>乘法
std::divides<T>除法
std::equal_to<T>相等比较
std::less<T>小于比较
std::greater<T>大于比较

示例:

#include <functional>
#include <iostream>

int main() {
std::plus<int> add;
std::less<int> less;

std::cout << add(3, 4) << '\n';
std::cout << (less(2, 5) ? "true" : "false") << '\n';
return 0;
}

与算法配合

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

int main() {
std::vector<int> nums;
nums.push_back(1);
nums.push_back(3);
nums.push_back(2);

std::sort(nums.begin(), nums.end(), std::greater<int>());

for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << ' ';
}
std::cout << '\n';

return 0;
}

bind1st / bind2nd(C++98 常见)

在 C++98 里,可以用 bind1stbind2nd 预绑定参数:

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

int main() {
std::vector<int> nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
nums.push_back(4);

int c = std::count_if(nums.begin(), nums.end(), std::bind2nd(std::greater<int>(), 2));
std::cout << c << '\n'; // 统计 > 2 的个数

return 0;
}

not1 / not2

可对谓词结果取反:

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

int main() {
std::vector<int> nums;
nums.push_back(0);
nums.push_back(1);
nums.push_back(0);

int zeros = std::count_if(nums.begin(), nums.end(), std::not1(std::bind2nd(std::not_equal_to<int>(), 0)));
std::cout << zeros << '\n';
return 0;
}

使用注意

  1. C++98 中 <functional> 很常用,C++11 以后许多场景会改用 lambda。
  2. bind1st / bind2nd 表达能力有限,复杂逻辑可自定义函数对象。
  3. 谓词要满足算法语义要求,避免副作用过重。