在C ++ 17中,std::map
和std::unordered_map
获得了一个新的成员函数模板:try_emplace()
。 n4279中提出的这一新增内容与emplace()
的行为类似,但具有以下优势:
try_emplace()
不会从rvalue参数移动。这在处理值为仅移动类型的地图时非常有用,例如std::unique_ptr
。try_emplace()
分别处理mapped_type
的密钥和参数,这使得它比用value_type
表示的通用变更器更直观(std::pair
})。鉴于上述优点,在编写C ++ 1z代码时,您是否会使用C ++ 11中的emplace()
而不是C ++ 1中的try_emplace()
?
答案 0 :(得分:27)
try_emplace
确实可以取代emplace
的大部分用途,但如果您有map
的不常用例,其中包含不可复制且不可移动的密钥类型,try_emplace
将无法正常工作,因为它会复制或移动密钥。在这种情况下,您必须使用emplace
和std::pair
的{{3}}来避免复制和移动。
即使你的密钥类型是可复制的和/或可移动的,分段构造是避免复制或移动构造密钥的唯一方法,因此可能存在超过try_emplace
的情况。
答案 1 :(得分:9)
try_emplace
也不支持异构查找 - 它不能,因为它需要密钥。
假设我们有std::map<std::string, int, std::less<>> counts;
和std::string_view
sv
。我想做相当于++counts[std::string(sv)];
,但我不想创建一个临时的std::string
,这只是浪费,特别是如果字符串已经存在于地图中。 try_emplace
无法帮助你。相反,你会做类似
if(auto lb = counts.lower_bound(sv); lb != counts.end() && lb->first == sv) {
++lb->second;
}
else {
counts.emplace_hint(lb, sv, 1);
}
答案 2 :(得分:5)
我总是喜欢try_emplace over emplace。一个关键的区别是,如果密钥已经存在,try_emplace将不会构造与密钥关联的对象。如果该类型的对象创建起来很昂贵,这将提高性能
例如以下代码(来自https://github.com/PacktPublishing/Cpp17-STL-Cookbook/blob/master/Chapter02/efficient_insert_or_reassign_to_map.cpp的示例)
#include <iostream>
#include <functional>
#include <list>
#include <map>
using namespace std;
struct billionaire {
string name;
double dollars;
string country;
};
int main()
{
list<billionaire> billionaires {
{"Bill Gates", 86.0, "USA"},
{"Warren Buffet", 75.6, "USA"},
{"Jeff Bezos", 72.8, "USA"},
{"Amancio Ortega", 71.3, "Spain"},
{"Mark Zuckerberg", 56.0, "USA"},
{"Carlos Slim", 54.5, "Mexico"},
// ...
{"Bernard Arnault", 41.5, "France"},
// ...
{"Liliane Bettencourt", 39.5, "France"},
// ...
{"Wang Jianlin", 31.3, "China"},
{"Li Ka-shing", 31.2, "Hong Kong"}
// ...
};
map<string, pair<const billionaire, size_t>> m;
for (const auto &b : billionaires) {
auto [iterator, success] = m.try_emplace(b.country, b, 1);
if (!success) {
iterator->second.second += 1;
}
}
for (const auto & [key, value] : m) {
const auto &[b, count] = value;
cout << b.country << " : " << count << " billionaires. Richest is "
<< b.name << " with " << b.dollars << " B$\n";
}
}
对于上面的代码
m.try_emplace(b.country, b, 1);
如果插入不成功,则不会构造对,这会增加性能