如果键已经存在,为什么 stl map 会插入另一个值,而不仅仅是更改它

Why stl map inserts another value if key already exist, and not just change it?

本文关键字:另一个 不仅仅是 插入 map 存在 为什么 如果 stl      更新时间:2023-10-16

为什么我的程序使用 STL 映射在键已经存在时插入值而不是更改现有值?

#include <iostream>
#include <map>
using namespace std;
struct CTest
{
    int a, b, c;
    CTest(int A, int B, int C) : a(A), b(B), c(C) {}
};
bool operator<(const CTest & l, const CTest & r)
{
    if(l.a < r.a) return true;
    else if(l.a > r.a) return false;
    if(l.b < r.b) return true;
    else if(l.b > r.b) return false;
    if(l.c < r.c) return true;
    else if(l.c > r.c) return false;
    return true;
}
struct CTest2
{
    bool operator<(const CTest2 & r) const
    {
        return q < r.q && w < r.w;
    }
    int q,w;
    CTest2() : q(0), w(0) {}
    CTest2(int Q, int W) : q(Q), w(W) {}
};
int main()
{
    // map of maps
    map<CTest, map<string, CTest2> > x;
    x[CTest(1,1,1)]["lol"] = CTest2(1,2); // x[CTest(1,1,1)]["lol"] now stores CTest2(1,2)
    x[CTest(1,1,1)]["lol"] = CTest2(3,4); // CTest2(1,2) must be changed to CTest2(3,4)
    x[CTest(1,1,1)]["lol"] = CTest2(5,6); // now to CTest2(5,6)
    x[CTest(2,1,0)]["ha"] = CTest2(11,12);
    for(map<CTest, map<string, CTest2> >::iterator i = x.begin(); i != x.end(); ++i)
        for(map<string, CTest2>::iterator j = i->second.begin(); j != i->second.end(); ++j)
            cout << j->first << " " << j->second.q << " " << j->second.w << endl;
}

运行此打印:

lol 3 4
lol 1 2
ha 11 12

为什么会发生这种情况,我该如何解决?

std::map用于对元素进行排序的比较函数必须遵循严格的弱排序。但是您的实现不会这样做。根据您的实现,当所有成员(a、b、c)相等时,您的operator<返回true。换句话说,(1,1,1) < (1,1,1)返回true 。有意义吗?不。

一个简单的解决方法是:

bool operator<(const CTest & l, const CTest & r)
{
    if(l.a < r.a) return true;
    else if(l.a > r.a) return false;
    if(l.b < r.b) return true;
    else if(l.b > r.b) return false;
    return l.c < r.c;
}

这太啰嗦了。而不是<,如果你使用!=,以上将减少到这个:

bool operator<(const CTest & l, const CTest & r)
{
    if(l.a != r.a) return l.a < r.a;
    else if(l.b != r.b) return l.b < r.b;
    return l.c < r.c;
}

好吧,这仍然很冗长,您可以将其实现为:

bool operator<(const CTest & l, const CTest & r)
{
   return std::tie(l.a,l.b,l.c) < std::tie(r.a,r.b,r.c);
}

std::tie 函数返回其operator<实现弱排序std::tuple,因此请利用这一事实。

您的operator<()返回相等元素的true

您链接的代码在 operator < 中有一个错误:当键相等时,它会返回true。它在 'x[CTest(1,1,1)]["lol"] = CTest2(3,4); 处给出运行时调试断言。如果将return true;更改为return false;它将按预期工作。

CTest 的

相关文章: