C/C++ 谓词 lambda表达式
文章目录
- 前言
- 1. 引例
- 2. 谓词的含义
- 2.1 谓词运用
- 总结
前言
最近看lambda相关知识点,发现这个概念比较难以理解,看了几遍。可能是第一次正式接触STL的原因,对标准库的泛型编程理解不够深刻。
这篇博客就写一下lambda的相关。
1. 引例
在介绍谓词之前我们先来看下面的几个例子。
我们使用标准库的sort
函数,这个是默认为从小到大排序,是使用<
。
但是这个小于并非适用所有类型。因为它们可能没有明确定义的大小关系。
比如指针,两个指针分别指向两个数组。
int arr1[] = {1, 2, 3};
int arr2[] = {4, 5, 6};
int* p1 = arr1;
int* p2 = arr2;
// 这个比较没有定义
if (p1 < p2) {
// ...
}
再比如迭代器,两个迭代器分别指向两个vector容器。
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5, 6};
auto iter1 = vec1.begin();
auto iter2 = vec2.begin();
// 这个比较也没有定义
if (iter1 < iter2) {
// ...
}
针对这种情况,我们一般考虑函数重载,来做到自定义类型的比较。
比如下面这个例子,一个类对象之间进行比较,这个<
就并不适用了。
我们想比较同一个类两个对象之间的value值大小,必须得自定义“小于”
class MyClass {
public:
int value;
// 重载 < 运算符
bool operator<(const MyClass& other) const {
return value < other.value;
}
};
MyClass obj1{1};
MyClass obj2{2};
if (obj1 < obj2) {
// ...
}
在这个例子中,我采用了重载的方式自定义了“小于”,从而实现了类对象之间的value值比较。
在STL中,我们使用谓词,来达到这个目的。
2. 谓词的含义
谓词函数是一个返回布尔值的函数,通常用于作为算法的参数,用来定义元素的排序、筛选等行为。
在C++中,谓词函数可以是函数指针、函数对象(functor)、Lambda 表达式等。
2.1 谓词运用
现在我们打算比较两个单词长度,定义如下函数:
bool isShorter(const string &s1, const string &s2) {
return s1.size() < s2.size();
}
isShorter 就是一个谓词函数。
这个函数有两个参数,都是 const string & 类型的引用。这里使用引用是为了避免在函数调用时进行不必要的拷贝,提高效率。参数名为 s1 和 s2,分别表示两个待比较的字符串。
函数体内部只有一行代码,即 return s1.size() < s2.size();这行代码的作用是比较 s1 和 s2 的长度(使用 size() 函数),如果 s1 的长度小于 s2 的长度,则返回 true,否则返回 false。
我们现在使用如下语句对单词进行排序
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool isShorter(const string &s1, const string &s2) {
return s1.size() < s2.size();
}
int main()
{
vector<string> word={"edwinwzy","nice"};
sort(word.begin(),word.end(),isShorter);
for(auto &i:word){
cout<<i<<" ";
}
}
谓词函数在排序时,被用来判断两个元素的大小关系。在我的例子中,sort 函数调用时,会根据 isShorter 的比较结果来确定字符串的顺序。如果 isShorter(s1, s2) 返回 true,那么 s1 会被认为比 s2 “小”(或者说“短”),它们的相对顺序将被交换,从而实现按字符串长度升序排序的效果。
上面这个例子中,word.begin和word.end分别作为isShorter的s1,s2参数传入。这种支持两个函数传参的情况称为二元谓词
,如果是一个参数,那就是一元谓词
。
这个情况有点像本来不支持使用<
号的操作,我现在重载了这个运算符,只不过用可调用函数的方式进行改写,再传到STL中去。
总结
总结一下就是,谓词,作为标准库中的一个比较准则。这个比较准则是自定义的,是可调用的。我个人觉得有点像函数重载,只不过在STL中叫做谓词。当然后面lambda表达式对谓词的运用更进一步,后面再写。