C++:map自定義鍵比較函數

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"纔是偶然。

當設置了比較函數,應謹慎使用鍵類型爲指針的map對象,指針指向的空間可能無效噢!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章