c++ - 在 std::unordered_map 中移动插入/放置失败后恢复移动的元素
问题描述
std::unordered_map
我使用insert
oremplace
方法和移动语义填充 a 。当发生键冲突时,元素不会插入到地图中,但移动的元素无论如何都会被删除:
#include <unordered_map>
#include <iostream>
int main(){
std::unordered_map<int, std::string> m;
m.insert(std::make_pair<int, std::string>(0, "test"));
std::string s = "test";
// try insert
auto val = std::make_pair<int, std::string>(0, std::move(s));
if(m.insert(std::move(val)).second){
std::cout << "insert successful, ";
}else{
std::cout << "insert failed, ";
}
std::cout << "s: " << s << ", val.second: " << val.second << std::endl;
// try emplace
s = "test";
if(m.emplace(0, std::move(s)).second){
std::cout << "emplace successful, ";
}else{
std::cout << "emplace failed, ";
}
std::cout << "s: " << s << std::endl;
return 0;
}
输出:
insert failed, s: , val.second:
emplace failed, s:
因此没有插入任何内容,但对象(示例中的字符串)无论如何都会被删除,因此无法将其用于任何其他目的。可能的修复方法是不使用移动语义或在插入/放置之前检查密钥,这两者都有性能损失。
恢复,我理解移动语义意味着移动的对象处于仅对销毁有用的状态,但我不完全理解为什么失败的移动操作std::unordered_map
无论如何都会导致该状态,如果有任何允许避免这种情况而不会造成太多性能损失的代码模式。
解决方案
如果可以选择使用 C++17 功能,try_emplace
则仅当映射中不存在键时才会移动参数。
否则,您可以拥有自己的版本,通过组合find
和emplace
(或insert
)来获得(功能上)相同的效果。
请注意,如果它存在,这可能会比try_emplace
实现效率低(因为如果键不在地图中,您将在容器中进行 2 次搜索)。
推荐阅读
- zapier - Zapier 代码 XMLHttpRequest() 说 XMLHttpRequest 没有定义
- puppeteer - React-Select:如何为下拉列表的每个选项添加自定义类名?
- amazon-elastic-beanstalk - Amazon Route 53 域名,链接到 Elastic Beanstalk
- opencv - 图像数据生成器+自动标记+自动绘制基于对象分割的边界框
- grails - Grails 3.3.x 中的 SAML sp.xml 中的证书问题
- testing - 由于 Testcafe 前置请求 URL,对 API 端点的请求被拒绝 - 解决方案?
- python - 无法让 URL fstring 正常工作
- azure - 如何使用 Polyrepo 订购构建
- python - 按字母顺序排序篮球队字典
- angular - 使用 GitHub 使用 AWS Amplify 进行部署时无法承担指定的 IAM 角色