C++:map自定義比較函數
map容器可以自定義鍵比較函數。
例如,對某個map對象操作,鍵比較都忽略大小寫,如下:
main.C
#include <iostream>
#include <map>
#include <strings.h>
#include <algorithm>
using namespace std;
// 比較函數
struct MyCmp {
bool operator()(string l, string r) const { return strcasecmp(l.c_str(), r.c_str()) < 0; }
};
int main() {
map<string, int, MyCmp> mymap;
mymap["key"] = 0;
map<string, int, MyCmp>::iterator myit = mymap.find("KEY");
if (myit != mymap.end()) {
cout << "found!" << endl;
} else {
cout << "not found!" << endl;
}
return 0;
}
編譯 & 運行:
[test1280@localhost ~]$ g++ -o main main.C
[test1280@localhost ~]$ ./main
found!
在創建map對象時:
- 第一個string指明鍵類型;
- 第二個int指明值類型;
- 第三個MyCmp是個比較函數,指明“什麼樣的兩個鍵等價”;
比較函數實現中用strcasecmp忽略大小寫比較,因此,對設置了比較函數爲MyCmp的map對象操作,“key"等價於"KEY”,也等價於"Key"…
注意,比較函數返回一個bool類型的結果,即對兩個鍵進行比較,結果必定是true或者false。
如果,compare(key1, key2)返回false並且compare(key2, key1)返回false,則key1等價於key2。
踩過的坑!
main.C
#include <iostream>
#include <map>
#include <strings.h>
#include <algorithm>
using namespace std;
// 比較函數
struct MyCmp {
bool operator()(const char *l, const char *r) const { return strcasecmp(l, r) < 0; }
};
map<const char *, int, MyCmp> g_mymap;
void setKV() {
// 棧上對象
string key1 = "key";
g_mymap[key1.c_str()] = 1;
}
int main() {
setKV();
//string key2("XXX");
string key3("KEY");
map<const char *, int, MyCmp>::iterator myit = g_mymap.find(key3.c_str());
if (myit != g_mymap.end()) {
cout << "found!" << endl;
} else {
cout << "not found!" << endl;
}
return 0;
}
編譯 & 運行(在你的環境下執行,並不總是如下結果噢!):
[test1280@localhost ~]$ g++ -o main main.C
[test1280@localhost ~]$ ./main
found!
如果去掉key2那一行的註釋,重新編譯並運行:
[test1280@localhost ~]$ g++ -o main main.C
[test1280@localhost ~]$ ./main
not found!
當設置了比較函數並且使用指針作爲map的鍵類型需特別留意:鍵地址無效/非法。
g_mymap的鍵類型是const char *,是指針類型。
setKV函數給map對象增加了一對key-value,但是這裏的key1是一個棧上對象,保存到map中的鍵是一個棧上的地址值。
當函數調用完成,棧空間釋放,g_mymap中的key實際指向的是一個非法地址/無效地址。
此時再次比較查找key3等價於key1(非法地址/無效地址),“not found”是常態,"found"纔是偶然。