前记
template <class InputIter, class UnaryPredicate>
bool all_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
while (first != last) {
if (!unary_pred(*first++)) {
return false;
}
}
return true;
}
在学习这个STL基本算法 all_of 时,没看懂unary_pred 的语法。
理解 STL 算法 all_of 中的一元谓词 unary_pred
在 C++ STL 算法中,all_of 是一个常用的算法,用于检查指定范围内的所有元素是否满足某个条件。其核心在于理解一元谓词 unary_pred 的语法和作用。
unary_pred(*first) 的解析
*first:解引用迭代器first,获取当前迭代器指向的元素值。unary_pred:是一个一元谓词,可以是函数指针、函数对象、Lambda 表达式或普通函数。它接受一个参数(当前元素)并返回布尔值,表示该元素是否满足条件。
一元谓词的四种形式
1. 普通函数
普通函数是最简单的形式,接受一个参数并返回布尔值。
bool is_even(int x) {
return x % 2 == 0;
}
2. Lambda 表达式
Lambda 表达式是 C++11 引入的匿名函数,常用于简化代码。
auto is_even = [](int x) { return x % 2 == 0; };
3. 函数指针
函数指针指向一个普通函数,适合固定逻辑的场景。
bool (*predicate)(int) = is_even;
4. 函数对象(仿函数)
函数对象是一个类或结构体,重载了 operator(),可以保存状态。
struct IsEven {
bool operator()(int x) const {
return x % 2 == 0;
}
};
IsEven is_even_obj; // 实例化对象
lambda表达式和普通函数用的比较多,比较好理解,对于函数指针和函数对象这里需要补充讲一下。
函数对象 vs 函数指针的区别
| 特性 | 函数指针 | 函数对象(仿函数) |
|---|---|---|
| 类型 | 指向普通函数的指针 | 类或结构体,重载 operator() |
| 保存状态 | 不支持 | 支持(通过成员变量) |
| 灵活性 | 较低,仅能指向固定函数 | 高,可扩展行为或配置 |
| 使用方式 | 直接调用函数 | 调用对象的 operator() |
| 内存开销 | 较小(指针大小) | 可能较大(含成员变量) |
函数对象的优势:支持状态管理
函数对象的核心优势是能够保存状态,适用于需要动态配置的场景。例如,实现可定制的排序规则:
#include <vector>
#include <algorithm>
struct Compare {
bool reverse;
Compare(bool rev = false) : reverse(rev) {}
bool operator()(int a, int b) const {
return reverse ? (a > b) : (a < b);
}
};
int main() {
std::vector<int> v = {4, 2, 5, 1, 3};
// 正序排序
std::sort(v.begin(), v.end(), Compare());
// 输出:1 2 3 4 5
// 倒序排序
std::sort(v.begin(), v.end(), Compare(true));
// 输出:5 4 3 2 1
}
总结
- 普通函数/Lambda:适合简单逻辑,代码简洁。
- 函数指针:适合固定函数调用,无状态需求。
- 函数对象:适合需要保存状态或动态配置的场景,灵活性更高。
在实际开发中,Lambda 表达式和函数对象使用频率较高,而函数指针多见于兼容旧代码或特定设计模式。根据需求选择合适的形式,能让代码更清晰、高效。
参考:

被折叠的 条评论
为什么被折叠?



