C++中find_if函数predicate参数含义及使用异常排查
find_if的predicate参数说明 find_if属于STL算法库的范围查找函数,第三个参数**predicate(谓词)**是一个可调用对象,可以是普通函数、lambda表达式、重载了()运算符的仿函数,它的规则非常明确:
- 入参类型必须和迭代器指向的元素类型兼容
- 调用后返回值可隐式转换为
bool类型 - 查找过程中,算法会把范围内的元素逐个传入谓词,第一个让谓词返回
true的元素对应的迭代器就是find_if的返回值;如果整个范围都没有符合要求的元素,直接返回范围的尾后迭代器。
代码错误原因
你的代码有两处问题:
- 语法错误:
EvenNumber函数内return i%2==0语句末尾缺少分号,正常编译阶段就会报错。 - 核心逻辑错误:
find_if仅返回第一个满足条件的元素迭代器,不会一次性筛选出所有符合条件的元素。
你对vector排序后,内部元素顺序为0,1,2,3,4,5,6,7,8,9,10:- 传入
EvenNumber时,第一个满足偶数条件的元素是0,你拿到指向0的迭代器后直接遍历到容器末尾,自然会输出从0开始的所有元素,看起来和输出全部元素没有区别。 - 你认为
GreaterThanThree运行正确属于巧合:该谓词匹配到的第一个元素是4,从4开始到容器末尾的元素恰好都大于3,才造成了筛选成功的假象。如果容器排序后4后面存在小于3的元素,输出结果就会不符合预期。
- 传入
正确筛选所有偶数的实现
如果要获取范围内所有满足谓词条件的元素,有两种常用实现方式:
- 循环调用
find_if:每次找到符合条件的元素后,将查找起始位置移动到当前元素的下一位,直到返回尾后迭代器停止。 - 直接使用
copy_if算法:一次性将所有符合条件的元素拷贝到新容器中,逻辑更简洁。
修正后的可运行代码如下:
#include <iostream> #include <vector> #include <algorithm> using namespace std; bool EvenNumber(int i) { return i % 2 == 0; // 补全缺失的分号 } int main() { vector<int> v = {2,1,4,5,0,3,6,7,8,10,9}; sort(v.begin(), v.end()); // 循环find_if实现 auto it = v.begin(); while ((it = find_if(it, v.end(), EvenNumber)) != v.end()) { cout << *it << " "; it++; } /* copy_if实现 vector<int> even_res; copy_if(v.begin(), v.end(), back_inserter(even_res), EvenNumber); for (int num : even_res) { cout << num << " "; } */ return 0; }
上述代码运行后输出结果为:0 2 4 6 8 10,符合筛选所有偶数的预期。
内容的提问来源于stack exchange,提问作者Luistt0
相关产品推荐
相关产品推荐

