L.F的答案是使用
map::emplace
,如果map的值类型不需要构造函数,则这是正确的方法,因为每次调用构造函数都会像下面的示例一样被调用。
C++17带有略微不同的
insert_or_assign
。
可能最有效的解决方案是像这样做:
template <class M, class Vp>
std::pair<typename M::iterator, bool> insert_or_create(M& map, typename M::key_type&& k, Vp&& v) {
auto p = map.lower_bound(k);
if (p != map.end()) {
return std::make_pair(p, false);
}
return std::make_pair(map.emplace_hint(p, std::move(k), std::forward<Vp>(v)), true);
}
下面是一个示例来说明它的工作原理:
#include <sstream>
#include <iostream>
#include <string>
#include <map>
class Element {
public:
Element(int value) : value(value) {
std::cout << "Element ctor value = " + std::to_string(value) << std::endl;
}
int value;
};
template <class M, class Vp>
std::pair<typename M::iterator, bool> insert_or_create(M& map, typename M::key_type&& k, Vp&& v) {
auto p = map.lower_bound(k);
if (p != map.end()) {
return std::make_pair(p, false);
}
return std::make_pair(map.emplace_hint(p, std::move(k), std::forward<Vp>(v)), true);
}
int main(int argc, char **argv) {
std::map<int, Element> map;
auto& e1 = *map.emplace(1, Element(1)).first;
std::cout << "Element in map: " << std::to_string(e1.second.value) << std::endl;
auto& e11 = *map.emplace(1, Element(11)).first;
std::cout << "Element in map: " << std::to_string(e11.second.value) << std::endl;
auto e2 = *map.insert_or_assign(2, 2).first;
std::cout << "Element in map: " << std::to_string(e2.second.value) << std::endl;
auto e22 = *map.insert_or_assign(2, 22).first;
std::cout << "Element in map: " << std::to_string(e22.second.value) << std::endl;
auto e3 = *insert_or_create(map, 3, 3).first;
std::cout << "Element in map: " << std::to_string(e3.second.value) << std::endl;
auto e33 = *insert_or_create(map, 3, 33).first;
std::cout << "Element in map: " << std::to_string(e33.second.value) << std::endl;
}
这将会产生
Element ctor value = 1
Element in map: 1
Element ctor value = 11 <
Element in map: 1 <
Element ctor value = 2
Element in map: 2
Element ctor value = 22 <
Element in map: 22 <
Element ctor value = 3
Element in map: 3 <
Element in map: 3
这表明
insert_or_create
不会调用
Element
的构造函数。
我不确定为什么这样的函数没有出现在std::map接口中,因为它非常有用。
auto v = (m.find(k)!=m.end()?m[k]:"default")
,但与Elvis运算符相比,这太长且复杂了。 - Jerry Jeremiah