std::find_if 是 C++ 标准库 <algorithm> 中的一个算法,用于在区间中查找第一个满足指定谓词(条件)的元素。它比 std::find 更灵活,因为查找条件可以是任意可调用对象,而不只是“等于某个值”。
1. 头文件
cpp
#include <algorithm>
2. 函数签名
C++11 起的基本形式:
cpp
template<class InputIt, class UnaryPredicate> InputIt find_if(InputIt first, InputIt last, UnaryPredicate p);
C++17 起增加了执行策略重载:
cpp
template<class ExecutionPolicy, class ForwardIt, class UnaryPredicate> ForwardIt find_if(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, UnaryPredicate p);
3. 参数说明
| 参数 | 含义 |
|---|---|
first, last | 要搜索的区间 [first, last),左闭右开 |
p | 一元谓词,对每个元素调用,返回可转换为 bool 的值 |
谓词 p 可以写成:
-
普通函数
-
函数对象(仿函数)
-
Lambda 表达式
-
std::function -
绑定表达式等
谓词不应该修改传入的元素。
4. 返回值
-
如果找到第一个满足
p(*it) == true的元素,返回指向该元素的迭代器。 -
如果区间内没有元素满足条件,返回
last。
注意:返回的是迭代器,不是元素值。要取元素需解引用 *it。
5. 工作原理
std::find_if 从 first 开始,依次对每个元素调用谓词 p:
text
对 it = first, first+1, ..., last-1:
如果 p(*it) 为 true,立即返回 it
如果全部不满足,返回 last
它是线性查找,找到第一个匹配就停止。
6. 复杂度
-
最多进行
std::distance(first, last)次谓词调用。 -
时间复杂度为 O(N)。
-
对于输入迭代器即可工作,不要求随机访问。
7. 与 std::find 的区别
| 对比项 | std::find | std::find_if |
|---|---|---|
| 查找条件 | 元素是否等于某个值 | 元素是否满足任意谓词 |
| 参数 | value | 一元谓词 p |
| 灵活性 | 较低 | 很高 |
| 使用场景 | 精确值匹配 | 按条件查找,如大于、满足某属性、字符串包含某子串等 |
std::find 本质上是 std::find_if 的一个特例:条件为 *it == value。
8. 常见用法
按条件查找整数
cpp
auto it = std::find_if(v.begin(), v.end(),
[](int x) { return x > 10; });
查找结构体字段
cpp
struct Person {
std::string name;
int age;
};
auto it = std::find_if(people.begin(), people.end(),
[](const Person& p) { return p.age >= 18; });
查找字符串中包含子串的元素
cpp
auto it = std::find_if(names.begin(), names.end(),
[](const std::string& s) {
return s.find("Li") != std::string::npos;
});
配合 std::not_fn 或取反条件
cpp
auto it = std::find_if(v.begin(), v.end(),
std::not_fn([](int x) { return x % 2 == 0; }));
9. C++20 ranges 版本
C++20 提供了更简洁的 std::ranges::find_if:
cpp
#include <algorithm>
#include <ranges>
auto it = std::ranges::find_if(v, [](int x) { return x > 10; });
优点是:
-
可以直接传容器,不需要
begin()/end() -
支持投影(projection)
-
返回值与迭代器概念配合更好
-
对谓词约束更清晰
10. 注意事项
-
返回
last表示未找到,判断时通常写:
cpp
if (it != v.end()) { /* 找到 */ }
-
返回的是迭代器,取元素要解引用:
cpp
std::cout << *it;
-
谓词不应有副作用,也不应修改元素,否则行为不符合算法预期。
-
只找第一个匹配项。如果要找所有匹配项,应使用
std::find_first_of、循环调用,或std::ranges::find_if配合后续区间,或使用std::copy_if/std::remove_if等。 -
对已排序区间按值查找,可考虑
std::lower_bound/std::binary_search,复杂度 O(log N);但find_if的任意谓词条件通常无法利用有序性,除非条件本身适合二分。
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> v = {3, 7, 8, 12, 5, 20};
// 查找第一个大于 10 的元素
auto it = std::find_if(v.begin(), v.end(),
[](int x) { return x > 10; });
if (it != v.end()) {
std::cout << "找到第一个大于 10 的元素: " << *it << '\n';
std::cout << "下标: " << std::distance(v.begin(), it) << '\n';
} else {
std::cout << "没有找到满足条件的元素\n";
}
// 演示未找到的情况:查找大于 100 的元素
auto it2 = std::find_if(v.begin(), v.end(),
[](int x) { return x > 100; });
if (it2 == v.end()) {
std::cout << "没有找到大于 100 的元素\n";
}
return 0;
}
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/m0_73457176/article/details/168941549



