admin管理员组文章数量:1794759
C++ find find
C++ find find_if lambda表达式 理解和用法
find 和 find_if 都是stl 标准算法,标准库都已经提供了标准的算法了,那就直接用吧。令外说一下,如果要使用find find_if 等一系列函数需要包含 #include <algorithm> 头文件才可以。用到find_if 需要用到lambda表达式,正好一起记录了。
第一部分:代码展示。 第二部分:分析代码
1. 代码展示 #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详解](blog.csdn/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"); }好了基本的find和find_if 和lambda表达式 已经讲完了,以后有了新的想法接着更新。
2. 分析代码我们先看find的定义: template<class InputIterator, class T> InputIterator find (InputIterator first, InputIterator last, const T& val) { while (first!=last) { if (*first==val) return first; ++first; } return last; }
find查找一个标准类型的方式: find的实现就是通过==操作符来判断是否查找到,为什么对迭代器取引用就是值的本身,这个以后会写一片C++ 迭代器的文章,在这就不做深究了。这是标准类型的时候,如果列表里边用的不是标准类型而是一个类怎么办,就需要用到重载= =操作符了。
find 查找一个不是标准类型的值。 假如find查找的时候,迭代器里边存的不是标准类型,而是一个类对象,那就需要这个类重载==操作符了,在使用= =运算符的时候使用我们自己的重载函数来作对比。
加入查找的是一个对象指针怎么办,那就不能用find函数了,find函数接收对象类型,不能接受对象指针类型,那就需要用到了find_if函数。 看下find_if的实现:
first, last template<class InputIterator, class UnaryPredicate> InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred) { while (first!=last) { if (pred(*first)) return first; ++first; } return last; }
find_if 前两个参数和find一样,最后一个参数需要传入一个一元函数(也就是一个参数的函数) 用户定义的谓词函数对象,它定义要被搜索的元素满足的条件。谓词接受单个参数并返回true或false。 从说明可以看出来,第一个,第二个和find一样,第三个参数需要传递一个谓词来实现我们自己的判断。 *函数对象(也叫functor),听起来或许有点陌生,但他们是c++实体,即使你没有用过,也一定见过,只是你没有意识到而已。 从概念上讲,函数对象是用作函数的对象;但是从实现上来说,函数对象是实现了 operate()的类的对象。虽然函数和函数指针也可以归为函数对象,但实现了operate()的类的对象才能保存状态,才能用于STL。 我们直接看定义: - 一元函数:接受一个参数的函数,如f(x)。如果一元函数返回一个BOOL类型的值,则该函数称为谓词。 - 二元函数:接受2个参数的函数,如f(x,y)。如果二元函数返回一个BOOL值,则该函数称为二元谓词。 之所以给返回布尔类型的函数对象专门命名,是因为谓词是用来为算法判断服务的。 *谓词大体就说这些,后期会在写一篇专门介绍函数对象,和谓词的介绍
通过定制可以看出来,第三个参数需要传入一个函数对象,也就是谓词。实现方式有两种: 第一种:传入一个实现了operator()的类对象; 第二种:传入lambda表达式,lambda表达式本身就是函数对象,可以被stl应用。
本文标签: find
版权声明:本文标题:C++ find find 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686490454a73389.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论