一、等价与相等的简述
在容器中,等价并不是相等。为什么要提等价与相等呢?因为泛型算法中的find等用于比较的是相等,即以operator==为基础,而容器成员函数的比较是以operator<为基础,所以区分二者很重要。
1、相等
这个很好理解,operator==返回真即代表二者相等。注:二者相等只是函数返回真,具体规则程序员可以指定的。
2、等价
等价关系是以“在已排序的区间中对象值的相对顺序”为基础的(Effective STL).set map排序时,就是默认的使用这种方式。即每一个都不在另一个前面。代码示意为:
!(w1 < w1) && ! (w2 < w1)
3、一个忽略大小写的set程序实现:其中,忽略大小写的set执行的比较类型。
1 #include <string> 2 3 struct CIStringCompare{ 4 bool operator()(const std::string& lhs, const std::string& rhs) const 5 { 6 int flag = ciStringCompare(lhs, rhs); 7 if (flag < 0) return true; 8 else return false; 9 } 10 int ciStringCompare(const std::string &lhs, const std::string &rhs) const 11 { 12 return _stricmp(lhs.c_str(), rhs.c_str()); 13 } 14 };
1 #include <set> 2 #include <iostream> 3 #include "CIStringCompare.h" 4 #include <algorithm> 5 int main() 6 { 7 // 区分大小写 8 std::set<std::string> oriset; 9 oriset.insert("FuckC++"); 10 oriset.insert("fuckc++"); 11 12 // 不分大小写 13 std::set<std::string, CIStringCompare> testset; 14 testset.insert("FuckC++"); 15 testset.insert("fuckc++"); 16 17 std::cout << "区分大小写" << std::endl; 18 for_each(oriset.begin(), oriset.end(), [](const std::string& s)->void{std::cout << s << std::endl; }); 19 20 std::cout << "不区分大小写" << std::endl; 21 for_each(testset.begin(), testset.end(), [](const std::string& s)->void{std::cout << s << std::endl; }); 22 return 0; 23 }
显然,执行结果如下:
二、为包含指针的关联容器指定比较类型。
因为关联容器用等价进行排序,如果不指定比较类型,并且存储的是指针的话,会默认比较指针的值,而不是指针指向的对象。所以有必要对包含指针的关联容器指定比较类型。针对string*类型的如下:
struct StringPtrLess { bool operator()(const std::string *ps1, const std::string *ps2) const{ return *ps1 < *ps2; } };
typedef std::set<std::string*, StringPtrLess> stringPrtSet; stringPrtSet ssp; 。。。。// 操作
当然,这样每种类型都要写一个解引用的比较挺麻烦的,那么我们需要写一个模版:
struct DereferenceLess { template<typename PtrType> bool operator()(PtrType pt1, PtrType pt2) const{ return *pt1 < *pt2; } };
typedef std::set<std::string*, DereferenceLess> stringPrtSet; stringPrtSet ssp; // 会自动推断类型