//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" #include <vector> #include <algorithm> using namespace std; //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; class CA { public: int a; CA(int a) { this->a = a; } bool operator == (int t) { return a == t; } //无法编译 //friend bool operator == (const CA* ca,int t); }; //无法编译 /* bool operator == (const CA* ca,int t) { return ca->a == t; }*/ bool Compare(CA* f, CA* s) { return f->a < s->a; } template<class T1,class T2> vector<T1*>::iterator Find( vector<T1*>::iterator begin, vector<T1*>::iterator end, const T2& var) { while(begin != end) { if (*(*begin) == var) { return begin; } begin++; } } template<class T1,class T2> vector<T1*> FindRange( vector<T1*>::iterator begin, vector<T1*>::iterator end, const T2& var) { vector<T1*> result; while(begin != end) { if (*(*begin) == var) { result.push_back(*begin); } begin++; } return result; } /*** * 使用find_if */ static int globA = 1; bool prec (CA* ca) { if (globA == ca->a) return true; else return false; } vector<CA*> arry; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { arry.push_back(new CA(2)); arry.push_back(new CA(21)); arry.push_back(new CA(3)); arry.push_back(new CA(1)); arry.push_back(new CA(4)); arry.push_back(new CA(1)); arry.push_back(new CA(12)); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { sort(arry.begin(),arry.end(),Compare); for(unsigned i = 0; i < arry.size(); i++) { ShowMessage(IntToStr(arry[i]->a)); } vector<CA*>::iterator itor = find(arry.begin(),arry.end(),21); if (itor != arry.end()) { ShowMessage("find!"); } vector<CA*> range = FindRange<CA,int>(arry.begin(),arry.end(),1); ShowMessage("find "+IntToStr(range.size())+" number"); globA = 1; vector<CA*>::iterator itor2 = find_if(arry.begin(),arry.end(),prec); if (itor2 != arry.end()) { ShowMessage("find!"); } } //--------------------------------------------------------------------------- void __fastcall TForm1::FormDestroy(TObject *Sender) { for (unsigned i =0; i < arry.size() ;i++) { delete arry[i]; arry[i] = NULL; } arry.clear(); } //---------------------------------------------------------------------------
上述代码使用模板函数对vector<T*> 类的数组,进行查找。
标准库中的find 比较的方式如下:
template <class _RandomAccessIter, class _Tp> _STLP_INLINE_LOOP _RandomAccessIter __find(_RandomAccessIter __first, _RandomAccessIter __last, const _Tp& __val, const random_access_iterator_tag &) { _STLP_DIFFERENCE_TYPE(_RandomAccessIter) __trip_count = (__last - __first) >> 2; for ( ; __trip_count > 0 ; --__trip_count) { if (*__first == __val) return __first; //解除引用然后比较 ++__first; if (*__first == __val) return __first; ++__first; if (*__first == __val) return __first; ++__first; if (*__first == __val) return __first; ++__first; } switch(__last - __first) { case 3: if (*__first == __val) return __first; ++__first; case 2: if (*__first == __val) return __first; ++__first; case 1: if (*__first == __val) return __first; ++__first; case 0: default: return __last; } }
可以看见,标准库的实现是 *__first == __val ,要求实现 == 操作符。
然而,由于vector<T*> 内的元素都是指针,是无论如何也无法 满足==操作符比较的。
至于,为什么vector里面存指针?这关系到运行效率,指针拷贝成本低。
因此,如果vector<T*>这样的数组,基本考虑2种方式find
//自己实现一个Find泛型方法,不过依然要求实现操作符重载。
template<class T1,class T2> vector<T1*>::iterator Find( vector<T1*>::iterator begin, vector<T1*>::iterator end, const T2& var) { while(begin != end) { if (*(*begin) == var) { return begin; } begin++; } }
或者采用find_if
template <class _RandomAccessIter, class _Predicate> _STLP_INLINE_LOOP _RandomAccessIter __find_if(_RandomAccessIter __first, _RandomAccessIter __last, _Predicate __pred, const random_access_iterator_tag &) { _STLP_DIFFERENCE_TYPE(_RandomAccessIter) __trip_count = (__last - __first) >> 2; for ( ; __trip_count > 0 ; --__trip_count) { if (__pred(*__first)) return __first; ++__first; if (__pred(*__first)) return __first; ++__first; if (__pred(*__first)) return __first; ++__first; if (__pred(*__first)) return __first; ++__first; } switch(__last - __first) { case 3: if (__pred(*__first)) return __first; ++__first; case 2: if (__pred(*__first)) return __first; ++__first; case 1: if (__pred(*__first)) return __first; // ++__first; 我不知道为什么这里有这样的注释,C++ BUILDER 6 里面的代码就是这样的。可见,标准库也是人写的。 case 0: default: return __last; } }
从find_if 的实现可以看出,他的想法是传入一个类或者函数,把元素作为参数代入,如果函数返回true,就满足条件。
因此,使用了一个全局变量(实际应酌情考虑使用类成员)。
/*** * 使用find_if */ static int globA = 1; bool prec (CA* ca) { if (globA == ca->a) return true; else return false; }
//使用时
globA = 1;
vector<CA*>::iterator itor2 = find_if(arry.begin(),arry.end(),prec);
附带一个sort排序的例子(这个方式和C#,Java 里的方式差不多,只不过 C# 和Java要求传入的是实现ICompare的接口而已,这里是函数指针,本质都是将“行为”传进去)
在元素遍历,查找,排序方面,C#和Java要优雅的多。也许C++11 解决了这个问题,没去研究了。
原文:http://www.cnblogs.com/songr/p/4555677.html