2011-04-11 46 views
0

請參閱以下代碼以更好地理解我的問題。插入C++ map STL容器失敗

class compareByValue {                    
    public:                       
    bool operator()(const string* s1, const string* s2) const          
    {                        
     if (s1 == s2)                     
     return true;                    
     if ((s1==NULL) || (s2==NULL))                 
     return false;                    
     return (0 == s1->compare(s2->c_str()));              
    }                                                
}; 

map<string*, string*, compareByValue> nodeIdToIpAddress; 

for (int i = 0; i < nrec; ++i) { 
    nodeIdToIpAddress[ptr1[i]] = ptr2[i];            
    cout << "Added " << *(ptr1[i]) << " , " << *(ptr2[i]) << endl; 
} 

cout << "map has " << nodeIdToIpAddress.size() << " elements!" << endl; 

我有一個映射維護指向字符串對象的鍵值對。我確定鍵和值都不是NULL指針。當我運行上述程序(當然,我跳過周圍的代碼以使其更容易理解),「添加......」打印49次。 ptr1 [i],ptr2 [i]是指向字符串對象的指針,不是NULL指針,因爲我的程序沒有段錯誤。

我遇到的問題是,當我在最後打印地圖大小時,它說地圖中只有1個元素。

如果有人能指示我找到修復方法,我將不勝感激。提前致謝。

編輯:@Mark解決方案工作像我的魅力。謝謝

EDIT2:在看到來自@Mark和@James的有價值的反饋之後,我想我不需要在我的地圖中存儲指向字符串的指針。我將更改我的代碼以將字符串存儲爲鍵/值,這意味着我不需要自定義比較器函子。非常感謝。

+0

我不知道答案(但),但你可以用'return * s1 == * s2'替換'compare'行嗎? – 2011-04-11 21:39:24

+0

我確實嘗試過這個選項。它只打印一個元素。 – Srikanth 2011-04-11 21:44:12

+0

哇...... compareByValue :: operator()'的實現保證DailyWTF發佈。 o.O – ildjarn 2011-04-12 01:06:31

回答

2

您的比較操作是不正確的。只要你可以假設,沒有空添加,如果發現任何可以拋出:

bool operator()(const string* s1, const string* s2) const          
{                        
    if (!s1 || !s2) throw std::runtime_error("Whatever"); 

    return *s1 < *s2; 
}                     

編輯:我應該在這裏的推理多一點已經制定。例如,您傳遞給std::map(或setsort)的比較操作必須滿足嚴格的弱排序。這基本上意味着,x OP xfalse,如果x OP ytrue然後y OP xfalse,並且x OP yy OP z意味着x OP z(以及有關項目的其他規則無法比較)。

你的功能在幾個方面不能滿足這個要求:if (s1 == s2)需要返回false。 if ((s1==NULL) || (s2==NULL))不能返回false,因爲這意味着null < anythinganything < null。您必須將其分開,然後爲s1返回true,在s2爲null時返回false。 return (0 == s1->compare(s2->c_str()));是不正確的,因爲它是一個三方面的結果,而不是一個<關係。

由於您指定不會插入空值,因此最簡單的解決方案似乎是在該情況下拋出異常(如果任一個爲null),然後使用字符串內置運算符。除非你有實際的證據證明它是一個性能瓶頸,否則我會強烈地考慮不要通過容器中的指針存儲字符串。更簡單的設計更容易維護和保持正確,這往往會導致更好的方案長期。

+0

我的大巴掌。我怎麼忘記<運營商超載。謝謝。它的作用像魅力! :-) – Srikanth 2011-04-11 21:51:11

6

你的比較是錯誤的:if (s1 == s2)必須回報false和比較必須產生strict weak ordering

[對於它的價值,使用指針類型作爲一個std::map關鍵是不尋常的最好的。]

+0

如果容器中出現空值,則空檢查也是錯誤的:它不服從嚴格的弱排序。 – 2011-04-11 21:39:04

+0

此外,他似乎想要的是默認行爲,所以解決該問題的辦法是完全刪除函子。但有可能是其他問題... – Potatoswatter 2011-04-11 21:41:26

+0

我不相信,但讓你建議的變化沒有任何區別。 – Srikanth 2011-04-11 21:43:14