插入到c ++ map STL容器失败

时间:2011-04-11 21:34:34

标签: c++ stl map

请参阅以下代码以更好地理解我的问题。

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的有价值的反馈后,我想我不需要在地图中存储指向字符串的指针。我将更改我的代码以将字符串存储为键/值,这意味着我不需要自定义比较器仿函数。非常感谢。

2 个答案:

答案 0 :(得分:6)

您的比较器错误:if (s1 == s2) 必须返回false且比较器必须产生strict weak ordering

[对于它的价值,使用指针类型作为std::map的键是充其量的。]

答案 1 :(得分: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 xfalsex OP y,{ {1}}隐含y OP z(以及有关无法比较的项目的其他规则)。

你的功能在几个方面没有满足这个要求:x OP z需要返回false。 if (s1 == s2)无法返回false,因为它会暗示if ((s1==NULL) || (s2==NULL))null < anything。您必须将其拆分并为anything < null null返回true,并为s1 null返回false。 s2不正确,因为它是一个三向结果而不是return (0 == s1->compare(s2->c_str()));关系。

由于您指定永远不会插入空值,因此最简单的解决方案似乎是在这种情况下抛出异常(如果为null),然后使用字符串内置运算符。

现在所说的一切,我强烈建议不要将指针存储在容器中,除非你有实际的证据证明它是性能瓶颈。更简单的设计更容易维护和保持正确,这往往会带来更好的长期计划。