严格弱排序:如果x<y为true,那么!(y<x)为true,可以理解为俩个数据正序逆序传入比较函数中,得到的结果需要一致。
如果需要给map自定义key,那么key要支持operator<,并且operator<是严格弱排序的,如果不是严格弱排序,结果是未定义的(可能死循环,可能值被覆盖,windows和linux各种编译器版本之间也不一致)
如下程序中如果使用了错误的比较大小的方法,则在赋值时会崩溃,因为map在赋值或插入后会进行排序,当俩个数在比较的过程中,没有严格保证大小,则会导致崩溃
struct SKey
{
SKey(int a, int b, int c)
:m_a(a), m_b(b), m_c(c)
{
}
int m_a;
int m_b;
int m_c;
};
//正确的比较大小的方法
struct Skey_Right_Cmp
{
bool operator()(const SKey& left, const SKey& right) const
{
if (left.m_a < right.m_a)
return true;
else if (left.m_a > right.m_a)
return false;
if (left.m_b < right.m_b)
return true;
else if (left.m_b > right.m_b)
return false;
return left.m_c < right.m_c;
}
};
//错误的比较大小的方法
struct Skey_Wrong_Cmp
{
bool operator()(const SKey& left, const SKey& right) const
{
if (left.m_a < right.m_a)
return true;
if (left.m_b < right.m_b)
return true;
if (left.m_c < right.m_c)
return true;
return false;
}
};
//插入和删除测试,用错误的比较函数在执行map.erase时
//在gcc 4.1上可能导致死循环
template<typename KeyCmp>
void erase_test()
{
std::map<SKey, int, KeyCmp>data;
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)
for (int k = 0; k < 10; ++k)
data[SKey(i, j, k)] = 0;
assert(data.size() == 1000);
for (int i = 0; i < 1000; ++i)
{
std::cout << "erase" << i << "\n";
data.erase(SKey(std::rand() % 10, std::rand() % 10, std::rand() % 10));
}
}
int main()
{
std::cout << "begin right test....\n";
erase_test<Skey_Right_Cmp>();
std::cout << "begin wrong test....\n";
erase_test<Skey_Wrong_Cmp>();
std::cout << "test end" << std::endl;
}