请参阅以下代码以更好地理解我的问题。
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 :(得分: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
(或set
或sort
的比较操作)必须满足严格的弱排序。这基本上意味着x OP x
为false
,如果x OP y
为true
,则y OP x
为false
,x 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),然后使用字符串内置运算符。
现在所说的一切,我强烈建议不要将指针存储在容器中,除非你有实际的证据证明它是性能瓶颈。更简单的设计更容易维护和保持正确,这往往会带来更好的长期计划。