c++STL中的hash_map自定義類。
是的,hash_map是一個很方便的容器,有了STL確確實實給了C++developer很大方便,hash_map就是其中一種。他在資料少的時候,作用和基於RB-tree的map差不多,甚至不如,畢竟有hasher。但是在大量資料的時候,就很快捷了。我平時用hash_map都是用基本型別的,最多弄個string類,也是庫裡已經弄好了的。直接套模板就行。可是今天遇到一個問題就是當你需要把一個自定義類作為key的時候,應該怎麼辦?當我寫完程式並編譯的時候,他報錯了,報了很長的一段錯。前兩行是這樣的:
error C2784: “bool std::operator <(const std::list<_Ty,_Alloc> &,const std::list<_Ty,_Alloc> &)”: 未能從“const Box”為“const std::list<_Ty,_Alloc> &”推導 模板 引數
e:\program files\vc\include\list(1958) : 參見“std::operator <”的宣告
然後我根本不知道這是什麼問題,只好百度,百度裡基本說到都是忘記使用#include<string>,然而這並不是問題的關鍵,因為我並沒有用到字串啊,就是加上也是一樣報錯。
終於我耗時1h才找到隻言片語,又回頭看看錯誤報告,似乎是<的原因?沒有過載?是了,因為hash_map實現的時候需要用less也就是<函式來對key排序,那就把<過載了
bool operator<(const Box &k2)const { if ((*this).width != k2.width) { return (*this).width < k2.width; } if ((*this).depth != k2.depth) { return (*this).depth < k2.depth; } if ((*this).height != k2.height) { return (*this).height < k2.height; } return false; }
那麼應該可以了吧?結果還是報錯:
1>e:\program files\vc\include\xhash(30): error C2440: “型別轉換”: 無法從“const Box”轉換為“size_t”
1> 沒有可用於執行該轉換的使用者定義的轉換運算子,或者無法呼叫該運算子
那麼是跟size_t有關嘍,又用了1h我終於知道問題所在了,http://www.cplusplus.com/中的定義是這樣的
然後詳細情況如下:
是的少了個hasher,在《STL原始碼剖析》中,闡明瞭只有基本型別和字元指標可以呼叫預設hash函式。在使用了其他型別時(比如自定義類)使用者必須為其自定義一個hash函式像這樣:size_t operator() (const Box& b)const放在一個結構體中,作為仿函式,也就是函式物件。
我個人在這是這樣實現hasher的:
size_t operator() (const Box& b)const
{
return (b.depth + 10 * b.height + 100 * b.width) % 20;
};
本來以為總算可以了,然後還是報錯:1>e:\program files\vc\include\xhash(264): error C2039: “bucket_size”: 不是“cmp_key”的成員
1> c:\users\administrator\documents\visual studio 2013\projects\最高的箱子\最高的箱子\源.cpp(47) : 參見“cmp_key”的宣告
是的,真煩,bucket_size是什麼鬼啊,繼續查資料。。。
終於,我找到了,在http://www.cplusplus.com/中的定義是這樣的:
雖然是unordered_map不過定義應該差不多吧。而在stackoverflow中,大神是這麼說的:
在《STL原始碼剖析》中,是這麼說buckets的:hashTable表格內的元素為桶子(bucket),就是說表格內的每個單元,涵蓋的不只是個節點,甚至可能是一“桶”節點。
這就很明瞭了,我們可以在結果中加上:
enum
{ // parameters for hash table
bucket_size = 4, // 0 < bucket_size
min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N
};
必不可少的。然而還是報錯:
1>e:\program files\vc\include\xhash(744): error C2064: 項不會計算為接受 2 個引數的函式
1> 類不會將“operator()”或使用者定義的轉換運算子定義到指向函式的指標或指向函式的引用(它們接受適當數量的引數)
恩,過載<在此時來說是不行的,需要在結構體中加上:
bool operator()(const Box &k1, const Box &k2)const
{
if (k1.width != k2.width)
{
return k1.width < k2.width;
}
if (k1.depth != k2.depth)
{
return k1.depth < k2.depth;
}
if (k1.height != k2.height)
{
return k1.height < k2.height;
}
return false;
}
依然是仿函式,而不是過載運算子作為equalToKey()。這樣就全部完成了,全部程式碼在這:http://blog.csdn.net/youngstunner/article/details/50583852
完整的實現了一個自定義類的hash_map,大功告成!
相關推薦
c++STL中的hash_map自定義類。
是的,hash_map是一個很方便的容器,有了STL確確實實給了C++developer很大方便,hash_map就是其中一種。他在資料少的時候,作用和基於RB-tree的map差不多,甚至不如,畢竟有hasher。但是在大量資料的時候,就很快捷了。我平時用hash_map
Object-C中對自定義類實現協議
如果嘗試使用自定義類(例如,人類(person類)、地址簿類(myBook類)、分數類(Fraction類))中的copy方法,如 myBook = [myBook mutableCopy]; person = [Person copy];等類似的操作,將會收到一條異
問題解決——在STL的queue中使用自定義類
本文原創,轉載請保證文章的完整性,並顯要的註明出處。 平時很少用STL,就算用,也基本是使用queue<int>之類的簡單資料型別,偶爾在MFC裡寫點小程式碼,用的也是queue<CString>。 (求不要吐槽我為什麼用CString不用stri
Idea_學習_03_IDEA中使自定義類型的文件進行代碼高亮識別
segment tar register 定義 類型 自定義類 pos edi ref 如果你只是想用xml的編輯模式來編輯*.screen文件的話,可以在 Settings->Editor->File Types 中,在Recognized File Ty
Java中的自定義類和ArrayList<E>的使用案例
自定義類和ArrayList的使用 自定義類: 將生活中事物抽象成程式碼,或者說是對生活中事物的一種對映。 1.類是一種引用資料型別 2.類中包含了屬性和功能, 屬性:事物的特性,例如:name(姓名),gender(性別),color(顏色),brand(品牌),siz
map中使用自定義類指標作為key
//先上程式碼 #pragma once //想用類作為key,必須過載<運算子 或者提供 //想用指標作為key,也是可以的,不過要自己提供仿函式 class CBase { public: explicit CBase(int a); ~CBase(void); private:
C# WinForm中如何自定義config檔案(XML檔案),並且讀取和儲存它
我這裡以連結資料庫為例子, 其中書寫的Config的xml檔案如下: <?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add k
vector中存放自定義類 ,對類的要求
vector中存放自定義類的前提是: 自定義的類必須有預設建構函式。因為vector會呼叫預設建構函式來初始化元素的物件。 那必須要明確:編譯器什麼時候隱式宣告預設建構函式? 有兩個條件: · 該類沒有顯式宣告任何建構函式。--既然你都定義了,系統就不給你生成了。 · 資料
淺談VB6中的自定義類的使用
PS:除非特別宣告,本文所說VB指的是VB6,而非VB.NET。 大家都知道,VB是一種半面向物件(也有人稱之為“偽面向物件”)的語言,他雖然可以寫自定義的類,但是由於種種原因,使得他在這方面的發育產生了一點問題,比如說:VB寫出來的類是不能繼承的(不孕不育?!-_-#...傳說VB的偶像是東方
HashMap中使用自定義類作為Key時,為何要重寫HashCode和Equals方法
ide string https object 避免 equals方法 args sys 添加 之前一直不是很理解為什麽要重寫HashCode和Equals方法,才只能作為鍵值存儲在HashMap中。通過下文,可以一探究竟。 首先,如果我們直接用以下的Person類
c#中的自定義泛型類、泛型方法和泛型接口
泛型方法 return bsp 其中 tel sts code 方式 void ? 泛型的產生其中一個原因就是為了解決原來集合類中元素的裝箱和拆箱問題: 一、泛型類: /// <summary> /// 返回前臺的消息 /// &
C# 有關控件、自定義類事件中的委托鏈的獲取、移除操作
ons class 單擊 spa inf += finish ati pre 直接來代碼吧,這樣幹脆直接,也不耽誤我午休了。一切盡在源碼中。 public class ControlEventTool { /// <summary>
c++ STL 之 unorder_map及unorder_set使用自定義類作為key的方法
#include <iostream> #include <string> #include <unordered_map> #include <unordered_set> using namespace std; str
C#自定義類中操作主窗體控制元件,通過委託實現
主窗體中包含一個標籤label1和一個按鈕button1 程式碼如下: public void ChangeLabel(string text) { label1.Text = text; } private void button1_Click(o
C++中對hash_map自定義雜湊函式和比較函式的理解
#include "stdafx.h" #include <iostream> #include <hash_map> #include <vector>using std::vector; using stdext::hash_map;class hash_wchar_
Lambda語句中創建自定義類型時,也可指定某種特定類型,方法是在new與{}之間寫上類型名稱
特定 pan sel lambda語句 lam {} where distinct select 如: var fc =...ChildFath = fc.Select(c => new Child_Father { child = c.child, father =
工作總結 Rezor 裏面的一些小知識----自定義類型 放在標簽值中 會直接跳過去
直接 技術 例如 images 定義變量 png 索引 log blog 0 的時候不報錯 1 的時候 報錯了 原因 是 imagesname[i] 索引超出了 為什麽在 上面 報錯呢? 不在這裏報錯呢? 說明了 Rezor 對於 自定義的變量 放在標
java自定義類型 作為HashMap中的Key值 (Pair<V,K>為例)
由於 con als void hash system 進行 原型 自定義 由於是自定義類型,所以HashMap中的equals()函數和hashCode()函數都需要自定義覆蓋。 不然內容相同的對象對應的hashCode會不同,無法發揮算法的正常功能,覆蓋equals函
c/c++ 標準庫 set 自定義關鍵字類型與比較函數
尖括號 ios template end 傳遞函數 使用 out 例子 比較 標準庫 set 自定義關鍵字類型與比較函數 問題:哪些類型可以作為標準庫set的關鍵字類型呢??? 答案: 1,任意類型,但是需要額外提供能夠比較這種類型的比較函數。 2,這種類型實現了 &l
資料結構與演算法----自定義類中函式與資料成員
近期在梳理知識,做一個小結,希望自己能多多使用 在標頭檔案中: enum sign {plus, minus}; class Accruency { public: Accruency(sign s = plus, unsigned long d = 0, unsigned in