我正在开发一个需要唯一键和值的项目,所以我决定使用地图。对于有人可能想要更改键值的情况,一切都有效。我不确定为什么,但它会导致碎片错误。我可以不这样做吗?
void Journal::set_id(int id){ // journal class
if(join.count(id)){ // join is: static map <int,string> join
cout<<"Journal ID is already being used. Try again."<<endl;
}
else {
join.erase (join.find(id));
join.insert(pair<int,string>(id,name));
}
}
答案 0 :(得分:2)
你的逻辑是有缺陷的。
void Journal::set_id(int id){
if(join.count(id)){
cout<<"Journal ID is already being used. Try again."<<endl;
}
else {
// When you hit this block of the code, there is nothing
// in the map corresponding to 'id'.
// join.find(id) returns the same iterator as join.end()
// Calling erase() with that iterator is causing you the
// problem.
// Don't call erase. Just insert the new item.
// join.erase (join.find(id));
join.insert(pair<int,string>(id,name));
}
}
答案 1 :(得分:1)
您刚检查过以确保id
未被用作地图中的键。如果是,则发出错误。所以现在你知道 id
不在地图中。如果地图中没有id
,join.find(id)
将返回join.end()
,因此您根本不需要致电find
。但更重要的是,您再调用join.erase(join.end())
,这是一个错误。
请参阅documention for std::map::erase() in cppreference:
迭代器pos必须是有效且可解除引用的。因此,end()迭代器(有效但不可解除引用)不能用作pos的值。
答案 2 :(得分:0)
不是检查密钥是否存在,只有在找不到的情况下插入密钥,您可以通过插入项目来简化代码,然后检查返回值以查看插入是否成功(它赢得了&#39;如果那个钥匙已经存在了。)
void Journal::set_id(int id){
if (!(join.insert(std::make_pair(id, name)).second))
cout<<"Journal ID is already being used. Try again."<<endl;
}
这也应该提高速度,因为它只搜索树一次,而执行count
然后insert
的代码必须搜索两次。