用stl的find方法查找一個包含簡單類型的vector中的元素是很簡單的,例如
vector<string> strVec;
find(strVec.begin(),strVec.end(),”aa”);
假如vector包含一個復合類型的對象呢比如
class A {
public:
A(const std::string str,int id)
{
this->str=str; this->id=id;
}
private:
std::string str; int id;
};
這個時候一般的想法是寫個函數遍歷這個vector,然后進行比較查找。實際上在使用STL的時候,不建議使用循環遍歷的查找方法,有幾個理由(參加《effictive c++》46條): 效率:泛型算法通常比循環高效。 正確性: 寫循環時比調用泛型算法更容易產生錯誤。 可維護性: 與相應的顯式循環相比,泛型算法通常使代碼更干凈、更直觀。
實際上通過find_if泛型算法可以很優雅的達到期望的效果。
template<class InputIterator, class Predicate> InputIterator find_if( InputIterator _First, InputIterator _Last, Predicate_Pred );
這里的最后一個參數可是一個一元謂詞,即只帶一個參數且返回值限定為bool的函數對象,例如
bool compare(A& dValue)
{
if(dValue.GetStr().compare(“bb”)==0)
return true;
else
return false;
}
示例:
vector<A> a;
A b(“aa”,4);
A c(“bb”,6);
A d(“zz”,7);
a.push_back(b);
a.push_back(c);
a.push_back(d);
vector<A>::iterator t=find_if(a.begin(),a.end(),compare);
以上函數限定了比較的內容,如果我們想要靈活的自定義比較條件的話要如何做呢,有2個辦法,一個是自定義類 ,並重載()操作符號,例如:
class findx {
public:
findx(const string str){test=str;}
string GetTest() {return test;}
bool operator()(A& dValue) {
if(dValue.GetStr().compare(test)==0)
return true;
else
return false;
}
private:
string test;
};
比較的時候只要
vector<A>::iterator t=find_if(a.begin(),a.end(),findx(“33″));
還有一種方法是使用仿函數和綁定器。仿函數就是類似上面的重載了操作符()的自定義類,或者用struct也可以。因為他定義了操作符“()”,所以能夠像函數調用一樣在對象名后加上“()”,並傳入對應的參數,從而執行相應的功能。這樣的類型就是函數對象,從而能作為函數參數傳遞給find_if。
下面再說綁定器:
STL中的綁定器有類綁定器和函數綁定器兩種,類綁定器有binder1st和binder2nd,而函數綁定器是bind1st和bind2nd,他們的基本目的都是用於構造一個一元的函數對象。比如這里我們可以利用bind2nd通過綁定二元函數對象中的第二個參數的方式來實現二元謂詞向一元謂詞的轉換。
struct compare: binary_function<A, string,bool> {
bool operator()( A &value, string str) const
{
if (value.GetStr()== str)
return true;
else
return false;
}
};
示例:
vector<A>::iterator t=find_if(a.begin(),a.end(),bind2nd(compare(),”33″));
無論是用vector的循環還是find_if泛型算法,在性能和代碼復雜度上面都有一定得權衡,至於在實際應用中,還是需要具體問題具體分析的。
現在還是迷糊的,下面是自己在項目中看到的師傅寫的一個比較實用的方法:
template<typename T> bool compare_no(const T* s1 , const T* s2)
{
return strcmp(s1->no, s2->no) == 0;
}
template<typename T> bool less_no(const T* s1 , const T* s2)
{
return strcmp(s1->no, s2->no) < 0;
}
template<typename T> bool compare_id(const T* s1 , const T* s2)
{
return s1->id == s2->id;
}
template<typename T> bool less_id(const T* s1 , const T* s2)
{
return s1->id < s2->id;
}
//排序
std::sort(vct_device.begin(), vct_device.end(), less_id<ST_DEVICE>);
std::sort(vct_camer.begin(), vct_camer.end(), less_no<ST_CAMERA>);
//通過編號查找ID
vector<ST_CAMERA*>::iterator it_cam;
ST_CAMERA tmp_cam;
strcpy(tmp_cam.no, "888888");
it_cam = std::find_if(vct_camer.begin(),vct_camer.end(),bind2nd(ptr_fun(compare_no<ST_CAMERA>), &tmp_cam));
if (it_cam != vct_camer.end())
返回值channel = (*it_cam)->channel;
//通過ID查找編號
vector<ST_CAMERA*>::iterator it_cam;
ST_CAMERA tmp_cam;
int camid = 0;
tmp_cam.id = 3;
it_cam = std::find_if(vct_camer_secd.begin(), vct_camer_secd.end(), bind2nd(ptr_fun(compare_id<ST_CAMERA>), &tmp_cam));
if (it_cam == vct_camer_secd.end())
返回值strcpy(camera,(*it_cam)->no);