Nic*_*ori 5 c++ unordered-map move-semantics
我std::unordered_map使用insertoremplace方法和移动语义填充了一个。当发生关键冲突时,元素不会插入到地图中,但移动的元素无论如何都会被删除:
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
insert failed, s: , val.second:
emplace failed, s:
Run Code Online (Sandbox Code Playgroud)
因此,没有插入任何内容,但对象(示例中的字符串)无论如何都会被删除,从而无法将其用于任何其他目的。可能的修复方法是不使用移动语义或在插入/放置之前检查密钥,这两者都会造成性能损失。
要恢复,我理解移动语义意味着移动的对象处于仅对销毁有用的状态,但我不完全理解为什么失败的移动操作无论如何都会std::unordered_map导致该状态,以及是否有任何代码模式可以避免这种情况,而不会造成太多的性能损失。
如果可以选择使用 C++17 功能,则try_emplace仅当映射中尚不存在键时才会移动参数。
否则,您可以拥有自己的版本,通过组合find和emplace(或insert)来获得(功能上)相同的效果。
请注意,如果存在的话,这可能会比try_emplace实现效率低(因为如果键不在映射中,则需要在容器中进行 2 次搜索)。
| 归档时间: |
|
| 查看次数: |
637 次 |
| 最近记录: |