C++ find find_if 和 lambda表达式结合的理解和用法_湖边看驴的博客-CSDN博客_find_if lambda
#include "stdafx.h"
#include <algorithm>
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Demo
{
public:
Demo(int age, string name)
{
this->age = age;
this->name = name;
}
bool operator==(const Demo &another) const
{
std::cout << "进入Demo == 函数,比较变量:" << age << std::endl;
return (age == another.age);
}
int age;
string name;
};
typedef struct finder_t
{
finder_t(int n) : age(n) { }
bool operator()(Demo *another)
{
std::cout << "进入谓词函数,比较变量:" << another->age << std::endl;
return (age == another->age);
}
int age;
}finder_t;
int main(int argc, char *argv[])
{
/*1. 查找标准类型的数值,例如int,string*/
int value = 1;
list<int> list_1;
for (int i = 0; i < 10; i++) {
list_1.push_back(i);
}
list<int>::iterator list_it = find(list_1.begin(), list_1.end(), value);
if (list_it != list_1.end()) {
std::cout << "找到了value:" << value << std::endl;
}
else {
std::cout << "没有找到找到了value:" << value << std::endl;
}
/*2. 如果list里边存放着不是标准类型的数据,比如放着一个类,怎么办?
*需要重载==操作符,其实也就是自己实现比较的规则。
* */
list<Demo>list_2;
for (int i = 0; i < 10; i++)
{
Demo D(i, "cxtan");
list_2.push_back(D);
}
Demo demo = Demo(2, "cxtan");
list<Demo>::iterator list_it2 = find(list_2.begin(), list_2.end(), demo);
if (list_it2 != list_2.end())
{
std::cout << "找到了age:" << demo.age << std::endl;
}
else {
std::cout << "没有找到找到了age: " << demo.age << std::endl;
}
/*3. 另外一种情况就是list里边放着是对象指针,例如list<Demo *>,这时候怎么办,就不能用find了,因为重载==的参数是对象而不是对象指针
*这时候需要我们使用find_if 方法。查看find_if 的定义:
*template<class InputIterator, class Predicate>
InputIterator find_if(InputIterator _First, InputIterator _Last, Predicate _Pred);
Parameters
_First
An input iterator addressing the position of the first element in the range to be searched.
_Last
An input iterator addressing the position one past the final element in the range to be searched.
_Pred
User-defined predicate function object that defines the condition to be satisfied by the element being searched for. A predicate takes single argument and returns true or false.
用户定义的谓词函数对象,它定义要被搜索的元素满足的条件。谓词接受单个参数并返回true或false。
从说明可以看出来,第一个,第二个和find一样,第三个参数需要传递一个谓词来实现我们自己的判断。
*函数对象(也叫functor),听起来或许有点陌生,但他们是c++实体,即使你没有用过,也一定见过,只是你没有意识到而已。
从概念上讲,函数对象时用作函数的对象;但是从实现上来说,函数对象时实现了 operate()的类的对象。虽然函数和函数指针也可以归为函数对象,但实现了operate()的类的对象才能保存状态,才能用于STL。
我们直接看定义:
- 一元函数:接受一个参数的函数,如f(x)。如果一元函数返回一个BOOL类型的值,则该函数称为谓词。
- 二元函数:接受2个参数的函数,如f(x,y)。如果二元函数返回一个BOOL值,则该函数称为二元谓词。
之所以给返回布尔类型的函数对象专门命名,是因为谓词是用来为算法判断服务的。
*谓词大体就说这些,后期会在写一篇专门介绍函数对象,和谓词的介绍
* */
list<Demo *>list_3;
Demo *D = NULL;
int age = 3;
for (int i = 0; i < 10; i++)
{
D = new Demo(i, "cxtan");
list_3.push_back(D);
}
list<Demo *>::iterator list_it3 = find_if(list_3.begin(), list_3.end(), finder_t(age));
if (list_it3 != list_3.end())
{
std::cout << "找到了age:" << age << std::endl;
}
else
{
std::cout << "没有找到找到了age: " << age << std::endl;
}
/*
* 4. find_if可以实现查找函数指针的方法,find_if最后一个参数,是需要谓词的,但是每次定一个结构体去实现operator()去实现谓词函数岂不是很麻烦,所以我们可以使用
* lambda表达式来搞。
* lambda 定义:
* [capture list] (params list) mutable exception-> return type { function body }
* capture list:捕获外部变量列表
params list:形参列表
mutable指示符:用来说用是否可以修改捕获的变量
exception:异常设定
return type:返回类型
function body:函数体
常见的格式
1 [capture list] (params list) -> return type {function body} 声明了返回值,参数的
2 [capture list] (params list) {function body}省略了返回值类型,但编译器可以根据以下规则推断出Lambda表达式的返回类型: (1):如果function body中存在return语句,则该Lambda表达式的返回类型由return语句的返回类型确定; (2):如果function body中没有return语句,则返回值为void类型。
3 [capture list] {function body} 格式3中省略了参数列表,类似普通函数中的无参函数。
具体的lambda表达式的用法,请进入传送门:[lambda详解](https://blog.csdn.net/lcalqf/article/details/79401210)
下面开始使用lambda表达式来使用find_if
*/
list<Demo *>list_4;
Demo *D1 = NULL;
int age4 = 4;
for (int i = 0; i < 10; i++)
{
D1 = new Demo(i, "cxtan");
list_4.push_back(D1);
}
list<Demo *>::iterator list_it4 = find_if(list_4.begin(), list_4.end(), [age4](Demo *another) {
std::cout << "进入lambda表达式,比较变量:" << another->age << std::endl;
return (age4 == another->age);
});
if (list_it4 != list_4.end())
{
std::cout << "找到了age:" << age4 << std::endl;
}
else
{
std::cout << "没有找到找到了age: " << age4 << std::endl;
}
system("pause");
}