
测试时用的代码是这样的:
#include<iostream>
#include<set>
using namespace std;
class MyType
{
public:
int a, b, c;
MyType(int a, int b, int c):a(a), b(b), c(c){}
bool operator<(const MyType& myType) const
{
return a<myType.a;
}
};
int main()
{
set<MyType> se;
MyType type1(1,2,3);
MyType type2(1,2,4);
se.insert(type1);
se.insert(type2);
cout<<"The set size:"<<se.size()<<endl;
cout<<"Elements in the set as follows:"<<endl;
for(set<MyType>::iterator it = se.begin(); it != se.end(); it++)
{
cout<<"("<<it->a<<", "<<it->b<<", "<<it->c<<") ";
}
cout<<endl;
return 0;
}
结果很明显,当我已经把MyType(1,2,3)放到set中之后,就不能把MyType(1,2,4)放进去了。但是为什么呢?这两个对象看起来确实不一样啊!STL在比较是否相同的时候不是要比较每一个数据成员的吗?从上述的例子中,看到的确实不是这样的,STL不会自动的做任何比较,它仅对你说明过的动作干一些指定的活儿。在重载“<”的时候,当只指定众多数据成员中的一部分的时候,如果这部分都相同的话,set就认为是同一个元素了。就如上述所示一样,重载的时候仅作了a的比较,而没有说明如果a相同的话,是否对剩下的元素进行比较。这样一来,set认为MyType(1,2,3)和MyType(1,2,4)是一样的。要让set正确的进行大小的比较,针对自定义类型,就必须说明所有的数据成员的比较情况。如上述的例子的“<”重载,应该这样写:
bool operator<(const MyType& myType) const
{
return a<myType.a?true:(b<myType.b?true:c<myType.c);
}
这样一来,就完全说明了每一个数据成员的比较关系,set就可以正常工作了。还是MyType(1,2,3)、MyType(1,2,4)两个元素,这回运行的结果如下:

运行代码为:
#include<iostream>
#include<set>
using namespace std;
class MyType
{
public:
int a, b, c;
MyType(int a, int b, int c):a(a), b(b), c(c){}
bool operator<(const MyType& myType) const
{
return a<myType.a?true:(b<myType.b?true:c<myType.c);
}
};
int main()
{
set<MyType> se;
MyType type1(1,2,3);
MyType type2(1,2,4);
se.insert(type1);
se.insert(type2);
cout<<"The set size:"<<se.size()<<endl;
cout<<"Elements in the set as follows:"<<endl;
for(set<MyType>::iterator it = se.begin(); it != se.end(); it++)
{
cout<<"("<<it->a<<", "<<it->b<<", "<<it->c<<") ";
}
cout<<endl;
return 0;
}
摘自 Martin's Tips