std :: map的奇怪行为

时间:2014-05-22 07:49:01

标签: c++ stdmap

我有一个

std::map<a,std::vector<b>> m;

a是结构

struct a
{
  std::string c,d;
bool operator<(const a &o)
{ return !(c==o.c && d==o.d);}
}

我以这种方式填充地图

for(/*blah blah*/)
{
  m[A].push_back(B)
}

在填充后我正在打印一些东西

std::cout << "Size:" << m.size() << std::endl;
int i=0;
for(std::map<a,std::vector<b>>::iterator it = m.begin(); it != m.end();i++,it++)
{
   std::cout << "[" <<i <<"] " << it->second.size() << std::endl;
}

我得到的输出是

Size: 12
[0] 1
[1] 3

有人可以解释为什么map :: size()在迭代2个元素时显示12?

2 个答案:

答案 0 :(得分:3)

将比较功能更改为

bool operator<(const a &o) const
{
    if ( c == o.c )
         return d < o.d;

    return c < o.c; 
}

请注意,将其作为非成员函数通常更有用。

您的比较功能必须遵循以下规则:

  

如果我们将equiv(a, b)定义为!comp(a, b) && !comp(b, a),那么要求就是comp   和等同都是传递关系:

     

- comp(a, b) && comp(b, c)隐含comp(a, c)

     

- equiv(a, b) && equiv(b, c)隐含equiv(a, c)

地图使用比较函数生成数据结构并迭代它,所以如果你的函数错误,那么任何事情都可能发生。

答案 1 :(得分:2)

出于好奇,我在VS2010中尝试了这段代码。它不会编译。

bool operator<(const a &o) { return !(c==o.c && d==o.d); }

错误如下。

  

错误C2678:二进制'&lt;' :没有找到哪个运算符带有'const StdMapTest :: Exec :: a'类型的左手操作数(或者没有可接受的转换)

bool operator<(const a &o) const { return !(c==o.c && d==o.d); }

以上一行编译,但抛出一个断言:

  

表达式:无效的运算符&lt;

最后我试了这个。

    bool operator<(const a &o) const { return (c == o.c) ? d < o.d : c < o.c; }

编译并且似乎正常工作。

我认为可以公平地说,一个足够好的编译器会使这个问题变得不必要。我确信VS2010不是唯一可以进行此类诊断的人。