std::set 在使用 std::set.erase 后包含重复元素
std::set contains duplicate element after using std::set.erase
嗯,我需要设计一个播放器计时器,该计时器将为每个玩家执行一次 30 分钟。
我没有循环所有玩家,而是做了一个std::set<std::pair<playerid,last_time_executed>>
(两者都是整数std::set<std::pair<int,int>>
),并且:
- 我知道如何按时间值排序,
- 我知道如何在不插入重复玩家 ID 的情况下插入元素(集合中的一个玩家 ID)
但是我不知道如何仅通过 playerid 擦除元素,所以我用我的大脑选择的随机值做了一些测试,结果是:
#include <iostream>
#include <set>
typedef std::pair<int, int> Pair;
struct Cmp{bool operator ()(const Pair &a, const Pair &b){return a.second < b.second;}};
std::set<Pair, Cmp> myset;
int main() {
myset.insert(Pair(0, 5));
myset.insert(Pair(1, 0));
myset.insert(Pair(1, 1));
myset.erase(Pair(0, 698));
std::cout << myset.size() << std::endl;
for (auto i : myset)
std::cout << "(" << i.first << "," << i.second << ")" << std::endl;
return 0;
}
这实际上打印了....(请注意重复的 ID "1")
3(1,0)(1,1)(0,5)
虽然这:
int main() {
myset.insert(Pair(0, 5));
myset.insert(Pair(1, 0));
myset.insert(Pair(1, 1));
std::cout << myset.size() << std::endl;
for (auto i : myset)
std::cout << "(" << i.first << "," << i.second << ")" << std::endl;
return 0;
}
打印这个(没有重复的 ID?
阿拉伯数字(1,1)(0,5)
现在更stangely(!)这个:
int main() {
myset.insert(Pair(0, 5));
myset.insert(Pair(1, 0));
myset.insert(Pair(1, 1));
myset.erase(Pair(0, 0));
std::cout << myset.size() << std::endl;
for (auto i : myset)
std::cout << "(" << i.first << "," << i.second << ")" << std::endl;
return 0;
}
打印这个(没有重复的 ID?
阿拉伯数字(1,1)(0,5)
这真的很令人惊讶,因为我期望与第一次测试中的输出相同。
为什么会这样?
您的比较谓词仅比较该对的second
字段。
第一个字段中的"碰撞"无关紧要。
更改它以获得您描述的行为:
struct Cmp {
bool operator()(const Pair &a, const Pair &b) { return a.first < b.first; }
};
住在科里鲁
此外,正如其他人所注意到的,这更像是std::map<idtype, valuetype>
:
住在科里鲁
#include <iostream>
#include <map>
std::map<int, int> myset;
int main() {
mymap.emplace(0, 5);
mymap.emplace(1, 0);
mymap.emplace(1, 1);
mymap.erase(0);
std::cout << myset.size() << std::endl;
for (auto i : myset)
std::cout << "(" << i.first << "," << i.second << ")" << std::endl;
return 0;
}
请注意,要实际更新(现有)键的值:
mymap[0] = 5;
mymap[1] = 0;
mymap[1] = 1;
std::set
使用比较器"确定元素在容器中遵循的顺序以及两个元素键是否等效"。
由于您的比较器仅比较last_time_executed
,因此如果它们具有相同的last_time_executed
,则认为两个Pair
等效。因此,当您执行myset.erase(Pair(0, 0));
时,它会擦除Pair(1, 0)
。
当我运行您的第二个示例时,我得到了重复的玩家 ID,正如我所期望的那样。
相关文章:
- 在声明中合并两个常量"std::set"(不是在运行时)
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将 std::set 与基于键的比较器一起使用
- 修改"std::set"中用户定义类型的值
- 如何在构造函数参数中初始化"std::set"?
- 如何使用 lower_bound/upper_bound 从 std::set 获取索引号?
- 如何在 C++ 中转发声明 std::set?
- 重构使用动态强制转换的 std::set 的比较运算符
- 为什么 std::set.erase(first, last) 会影响从中获取 (first, last) 的容器?
- std::set 是否将对象连续存储在内存中?
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- 有什么理由不扩展 std::set 以添加下标运算符吗?
- 我从 std::set 得到const_iterator而不是迭代器
- 为什么 std:set(带有单个冒号)可以编译?
- 遍历 std::set 中包含的所有三重不同值?
- 插入 std::set 作为 std::map 的键
- 如何在 c++ 中使用默认值将 std::set 转换为 std::map
- 错误:'class std::unique_ptr<std::set<long unsigned int> >'没有名为 'size' 的成员
- 如何从 std::set 绘制 n 个元素的样本
- 为什么 std::set 容器使用的内存比其数据大小多得多?