2014-10-27 68 views
-2

我需要在C++上編寫我自己的哈希映射。它有一個方法.get(「some_string」)如果這個字符串不在我的hash_map我返回NULL。但我不能檢查我的程序,如果這個函數返回NULL或字符串。這是我的代碼:在成本字符串和函數中返回NULL

if (m.get("some_string")) 
    cout << m.get("some_string"); 

和方法:

const string& Map::get(const string& s) { 
    string_node* pos = find_pos(s); 

    if (pos) 
     return pos->val; 
    else 
     return NULL; 
} 

POS-> VAL只是一個字符串。所以我有一個錯誤,我不能從常量字符串轉換爲布爾。 問題是我需要做的,爲了防止cout中的錯誤,我的函數返回NULL。我如何檢查它?

+2

當你返回NULL時,你在這裏得到未定義的行爲。該函數必須構造一個「string」對象來返回,它使用'NULL'作爲'string'構造函數的參數。這調用'string'的'char *'構造函數,它有一個不傳遞空指針的前提條件。因此,您因違反先決條件而得到UB。另外,你應該得到關於返回一個本地對象的引用的警告,這將返回一個懸而未決的引用。您應該在啓用警告的情況下進行編譯,並且您應該注意所獲得的警告。 – bames53 2014-10-27 17:23:39

+0

@ bames53我認爲NULL被定義爲0,並且字符串沒有隱含的構造函數來取整數,所以甚至不會編譯。 – 2014-10-27 17:31:10

+0

@ bames53當我寫'return'「'的時候,我有一個警告,但是當我寫'return NULL'時沒有任何警告。它編譯時,當我在'find_pos'變量中返回'NULL'時,'pos'爲'0',所以我可以寫'if(pos)' – PepeHands 2014-10-27 17:31:54

回答

6

您不能爲const string&返回空值。您必須返回一個對實際字符串對象的引用,該對象在函數返回後將繼續存在。

選項:

  • 返回一個const string *它可以爲null

  • 在空的情況下拋出異常。

  • 按值返回一個字符串,並返回一個空的(但有效的)空字符串。這有兩個缺點。它複製結果,並且不能再識別null情況和真正的空字符串值,而無需從函數中輸出更多信息。

+1

我認爲一個空字符串也可能是一個選項。那是什麼std :: map做的。 – SHR 2014-10-27 17:20:58

+0

或者使用輸出參數並返回bool是否成功。 – clcto 2014-10-27 17:22:21

+0

@clcto沒有理由這樣做,因爲指針已經可以傳遞空值,並且不會強制複製該值。 – cdhowie 2014-10-27 17:23:15

0

如果您要返回引用,則不能返回NULL。儘管如此,你可以有一個特殊的返回案例讓它返回一個空的字符串引用,表示哈希不存在。

+2

如果空字符串是存儲在此映射中的有效值,該怎麼辦? – cdhowie 2014-10-27 17:16:32

+0

然後不要使用空字符串。當然,最終會由於實施的具體程度而決定。但知道你的散列函數是否可以返回一個空字符串可能是你應該知道的,即使你認爲返回這樣一個特例。 – sgtHale 2014-10-27 17:23:41

1

引用不能爲空,因此從函數返回NULL是沒有意義的。同樣,您使用const string&作爲條件,因此它會嘗試將其轉換爲布爾值,但沒有合適的轉換。相反,返回一個空字符串,並檢查返回值等於:

if (pos) 
    return pos->value; 
else 
    return ""; 


if(m.get("some_string") == "") { ... } 

如果一個空字符串是一個有效的值,那麼你可以使用一個輸出參數:

bool Map::try_get(const string& key, string& value) 
{ 
    string_node* pos = find_pos(s); 

    if (pos) 
    { 
     value = pos->val; 
     return true; 
    } 
    else 
    { 
     value = ""; 
     return false; 
    } 
} 
+2

如果空字符串是存儲在此映射中的有效值,該怎麼辦? – cdhowie 2014-10-27 17:15:32

+0

我不認爲一個空字符串會顯示爲散列。 – sgtHale 2014-10-27 17:17:08

+0

@sgtHale做出假設是最快的錯誤方式。 – cdhowie 2014-10-27 17:17:52

0

一個辦法處理可選的返回值是使用Boost.Optional。你可以簡單地使用它:

boost::optional<std::string> Map::get(const std::string& s) { 
    // ... 
} 

int main() 
{ 
    if (boost::optional<std::string> os = map.get("asdf")) 
    { 
     // *os 
    } 
} 
+0

(1)返回類型應該是'boost :: optional '(既不是const也不是引用)。 (2)請注意,這種方法會導致值被複制,以便按值返回,這會導致性能損失。 – cdhowie 2014-10-27 17:29:07

+0

@cdhow我本來就有這個,但是在重現OP的例子時遇到了麻煩。 – 2014-10-27 17:29:35