2017-03-02 65 views
0

我的問題是,爲什麼下面的代碼工作爲什麼散列<const char*>適用於字符串,但不適用於字符串變量?

hash<const char*> PassHash; 

cout << PassHash("Hello World"); 

但這個代碼不會編譯。

hash<const char*> PassHash; 
string password; 
password = "Hello World"; 

cout << PassHash(password); 

代碼塊中我得到這個錯誤

error: no match for call to '(__gnu_cxx::hash<const char*>) (std::string&)'| 
+4

由於'的std :: string'不是'爲const char *',並沒有適用的轉換運算符。使用'password.c_str()'。 [相關轉換問題](https://stackoverflow.com/questions/347949/how-to-convert-a-stdstring-to-const-char-or-char)。 – WhozCraig

+1

因爲'string'不是'const char *'...爲什麼'cout << PassHash(42);'不工作? – immibis

+0

ps的,如果你打算用這個實際的密碼 - 注意的std ::哈希並不在程序運行下一次一定會產生相同的輸出對於相同的輸入。 –

回答

1

沒有從std::stringconst char*的隱式轉換,這將使您的示例能夠正常工作。

你可以叫string::c_str()明確地這樣做「轉化」 ......

hash<const char*> PassHash; 
string password; 
password = "Hello World"; 

cout << PassHash(password.c_str()); 

...但由於沒有專門針對hash<const char*>這隻會計算哈希字符串指針的!所以這隻能匹配通用指針專用hash<T*>

你真正想要的是散列在字符串的整個字符數組上,所以如果字符串的一個字符改變了,你(很有可能)會得到不同的散列值。

爲此,您可以使用hash<std::string>專業化。如預期的那樣,這適用於const char*std::string參數,因爲std :: string的轉換構造函數需要const char*

實施例:

const char* password1 = "Hello World"; 
string password2 = "Hello World"; 

hash<const char*> charPtrHasher; 

// This only calculates a hash from the value of the pointer, not from 
// the actual string data! This is why you get a different hash for each. 
cout << "Test 1:\n"; 
cout << charPtrHasher(password1) << endl << charPtrHasher(password2.c_str()) << endl; 

hash<std::string> stringHasher; 

// This correctly calculates the hash over all characters of the string! 
cout << "\nTest 2:\n"; 
cout << stringHasher(password1) << endl << stringHasher(password2) << endl; 

現場演示:http://coliru.stacked-crooked.com/a/047c099f5dcff948

+0

到我的文章的編輯...有什麼問題'std :: string :: data()'?我認爲它增加了一致性(例如,比較'std :: vector :: data()')。 – zett42

+0

你可以參考[參考](http://en.cppreference.com/w/cpp/string/basic_string/data):「_返回的數組不需要以null結尾。」但是對於'hash '它沒有什麼區別,因爲它無論如何只是散列指針(C字符串沒有專門化)。 – zett42

3

std::hash具有類似於以下

template<typename T> 
struct hash { 
    size_t operator()(const T& value) const { 
    ... 
    } 
} 

的定義,所以這是微不足道的是std::hash<const char*>模板實例定義operator()它接受一個const char* ,但是您傳遞的是另一種類型的std::string

只需直接使用std::string代替密碼變量,然後使用std::hash<std::string>代替。

+0

您可以使用const char *'作爲'std :: hash '的參數,因爲它會隱式轉換爲std :: string。 'std :: hash '和'std :: hash '之間的更重要的區別在於前者僅散列指針,而後者散列整個字符串。 – zett42

+0

@ zett42:這是一個很大的差異,如果你不知道你在做什麼,使用'std :: hash '會導致奇怪的模糊行爲。例如,兩個'const char *'代表相同的序列,但分配在不同位置的堆上。 – Jack

相關問題