函数原型:
template <class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val);
功能:
查找[ first , last )范围内第一个与val相等的元素,返回其迭代器;若找不到,返回last。
例子:
运行如下:
Element found in myints: 30
Element found in myvector: 30
源码方面稍微有点麻烦,待我慢慢道来,先把源码贴上。
觉得源码挺长的,其实不然,真正的源码比这少了点,我之所以多加了代码是因为find的源码实现调用了其他地方,我也就顺便粘贴过来了。
应该很容易发现,上面的代码我分为了三部分,用两条横线隔开了,为了接下来更清晰的表述,我们姑且从上往下分别命名为:第一部分,第二部分,第三部分。
阅读源码应该从代码底部,一层一层的往上看,好,看源码的最后一个函数,它调用了上一层的函数,那我们再看上一层的函数,有点恐怖的感觉,许多||运算。那我们来看看这个有||运算的函数都做了什么,我可以先告诉你们这个函数是干嘛的,我们知道find函数有三个参数,两个同类型的的迭代器,还有一个特定比较值,那这个有许多||运算的函数其实就是对迭代器的类型做了分类讨论,一共两种情况,一种是指向字符,还有一种不是指向字符的。下面来说下原因。
要理解原因,只要理解两个结构体即可,就是is_same和integral_constant,关于这两个结构体的内容我也贴在源码的第三部分了。我们先来看integral_constant,在这个结构体我们只需关注两句代码,粘贴如下:
第一句,不用解释了,很简单;第二句,仿函数。
我们先跳过这个结构体,再看下面的两句代码:
true_type和false_type都是结构体类型,两句代码形式相似,我们就拿true_type来说吧。注意哦,把模板参数带入结构体我们发现,在true_type中,value已被赋值为true了,而在那个仿函数里,也返回了value(其实也就是true)。那么很容易知道false_type就是做了相反的事。
我们再来看is_same结构体,通过源码我们对这个结构体有两个明显的认识,一是继承了true_type/false_type结构体;二是这个结构体有因为模板参数的不同,有两种形式。通过对这个结构体的注释,我们也很容易知道这个结构体是干嘛的:“ determine whether _Ty1 and _Ty2 are the same type ” 。也就是说,true_type代表了 _Ty1 and _Ty2 are the same type;而false_type代表了different type。
好了,现在我们终于可以回过头看下那个有很多||运算的函数了,它在第三部分。我们再次贴出它的源码:
经过上面对integral_constant和is_same两个结构体的解析,我相信你已经看出端倪了。通过is_same判断_InIt参数类型是不是char *,signed char *,unsigned char *等中的一种,并且,注意还有一个&&运算,还要判断_Ty是否是一个整型。若都满足,就相当于 typedef integral_constant<bool,true> _Memchr_opt,进而利用仿函数作为_Find的第四参数。你可能好奇为什么这么做,请接着看:
现在我们来到源码的第二部分,不用读者急着翻哪个是第二部分的代码,我这里贴在下面,就两个函数:
注意看这两个函数第四参数,true_type代表_InIt是char *,signed char *,unsigned char *等中的一种,并且_Ty是整型类型的;那么false_type自然是反过来了。
很容易发现第四参数是false_type的,我们很容易看懂代码意思,其实到这里,你已经看到了find函数原始源码实现了,就这么简单。
我们还是重点看第四参数是true_type的,它调用了memchr,这个函数来自头文件<string.h>,读者可以查阅文档,看这个memchr的功能,至此,可以回答上面没解决的一个问题,为什么要分true_type和false_type两种形式的函数,原因很简单,为了效率。这个你只要知道memchr的意思就明白了,话说mem....系列的函数在对字节操作上都很高效,值得源码一探究竟。
源码摘抄自Visual Studio 2015安装目录algorithm文件中。
点击进入目录----> C++源码剖析目录