如何在STL的map中使用結構體作為鍵值


 

  這里首先給出容器map的原型:

template <
	class Key,
	class T, 
	class Compare = less<Key>,
	class Alloc = alloc>
class map{
	...
}

  可以看到模板參數一共有四個,第一個就是Key,即鍵;第二個就是值;第四個就是空間配置器,默認使用alloc(隨STL版本不同而不同)。那么第三個是啥?

  我們知道,map的底層數據結構,其實是樹,更確切的說,是一個RB-tree(紅黑樹)。RB-tree樹在進行插入時,會按照一定的規則把新元素插入特定位置。相應的,進行刪除操作時,也會按一定規則修改樹的結構。此外,樹形結構也是高效率查詢的基本保證。但是,插入、刪除、查詢時都要依賴與節點之間的比較,對於map來說,我們必須提供對Key進行比較的函數或操作符。這也就是第三個模板參數的意義。

  默認情況下,第三個模板參數使用less<Key>類型,其中less<T>是一個仿函數。下面給出less的定義:

template<class _Ty>
	struct less
		: public binary_function<_Ty, _Ty, bool>
	{	// functor for operator<
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator< to operands
		return (_Left < _Right);
		}
	};

  如果創建一個less類的對象less_obj,然后使用less_obj(A,B)這樣的寫法,就相當於調用了less的operator()方法。而最終執行時,會自動獲取A與B的類型,並使用此類型的operator<來實現less類的operator()方法。到現在為止,就理清了map中的第三個模板參數的所有問題。

  接下來的問題就是,如何在map中使用一個結構體作為Key。舉例來說,現在有一個結構體:

typedef struct _info_head{
	u_int src_ip;
	u_int dest_ip;
	u_int src_port; 
	u_int dest_port;
}info_head;

  如果直接使用info_head這個結構體來填入map中的第一個模板參數的位置,並且不指定第三個模板參數的話,那么就會使用less<info_head>作為map中對鍵值進行比較的操作符。而通過上述分析,在less<info_head>中最終使用的,是info_head類型的operator<操作符。那么顯然的,只給出上邊的簡單的對結構體的定義,是不夠的。因此,要想使用結構體來作為map中的Key,那就必須為此結構體重載並實現operator<操作符。如果沒能做到這一點,就會在編譯時報錯,因為編譯器找不到對應的operator<。其中,VS2010下的編譯錯誤代碼是:error C2784。

  修改后的結構體代碼如下:

typedef struct _info_head{
	u_int src_ip;
	u_int dest_ip;
	u_int src_port; 
	u_int dest_port;

	bool operator<(const struct _info_head & other) const {
	//Must be overloaded as public if this struct is being used as the KEY in map.
		if (this->src_ip < other.src_ip) return true;
		if (this->dest_ip < other.dest_ip) return true;
		if (this->src_port < other.src_port) return true;
		if (this->dest_port < other.dest_port) return true;
		return false;
	}
}info_head;

  不過這並不是唯一的辦法。另外一種方式,就是自己寫一個仿函數,實現對info_head類型的比較。然后在info_head作為map中第一個模板參數的時候,填入這個仿函數作為map的第三個模板參數。不過這樣做顯然不如上邊這種辦法簡單,這里也不具體敘述了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM