m0_73457176头像

深入理解C++ std::find_if

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::findstd::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. 注意事项

  1. 返回 last 表示未找到,判断时通常写:

cpp

if (it != v.end()) { /* 找到 */ }
  1. 返回的是迭代器,取元素要解引用:

cpp

std::cout << *it;
  1. 谓词不应有副作用,也不应修改元素,否则行为不符合算法预期。

  2. 只找第一个匹配项。如果要找所有匹配项,应使用 std::find_first_of、循环调用,或 std::ranges::find_if 配合后续区间,或使用 std::copy_if / std::remove_if 等。

  3. 对已排序区间按值查找,可考虑 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

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--