如果键已经存在,为什么 stl map 会插入另一个值,而不仅仅是更改它
Why stl map inserts another value if key already exist, and not just change it?
为什么我的程序使用 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 的
相关文章:
- C++从另一个类访问公共静态向量的正确方法是什么
- 在另一个类视图中添加最多2个图表的正确方法是什么
- 为什么这个案例陈述需要一个"if else"而不仅仅是一个"if"?
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 最佳做法是从另一个线程访问 qml 中的Q_PROPERTY
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 如果模板参数是另一个模板的实例化,则键入特征测试
- 将另一个类的对象传递到当前类C++的构造函数中(不是成员初始化)
- 将一个宏传递到另一个宏而不是直接传递内容时会出现不需要的额外"空"参数
- 如何正确实例化静态字段 tat 是另一个类对象
- 如何检查一个模板是否是另一个模板的类成员
- 是否可以将带有捕获和参数的 lambda 传递给另一个函数?如果是这样,如何?
- 将vector<vector<double>>从x86平台中创建的一个进程发送到x64中构建的另一个进程的最快方法是什么
- 如何设计一个始终是另一个类的成员的类
- 如何说一个有效或无效,即使一个是,另一个不是
- 使用 gtest EXPECT_CALL 时竞争条件段错误,而另一个期望是执行相同的方法
- 如果键已经存在,为什么 stl map 会插入另一个值,而不仅仅是更改它
- 用两个向量,一个变量是x, y, z,另一个值是1,2,3,来得到x=1, y=2, z=3的方程
- 一个字符串开始另一个字符串是什么意思?c++
- 另一个选项是双指针