我正在选择将东西放入unordered_map中的两种方法之一:
std::unordered_map<Key, Value> map;
map.emplace(
std::piecewise_construct,
std::forward_as_tuple(a),
std::forward_as_tuple(b, c, d));
vs
std::unordered_map<Key, DifferentValue> map;
auto& value = map[a];
if (value.isDefaultInitialized())
value = DifferentValue(b, c, d);
我做了一些实验,发现在插入唯一元素时,它们的表现相当。然而,在插入重复项时(考虑到 Value 或 DifferentValue 的构建不是微不足道的),令我惊讶的是,无论是否插入对象,emplace 都会构造对象。因此,在这种情况下,第二种方法似乎要胜出得多,因为默认构造函数只有 isDefaultInitialized_(true)而已,没有更多的功能。对于 emplace,代码似乎是:
... _M_emplace(std::true_type, _Args&&... __args) {
__node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
const key_type& __k = this->_M_extract()(__node->_M_v);
...
if (__node_type* __p = _M_find_node(__bkt, __k, __code)) {
_M_deallocate_node(__node);
return std::make_pair(iterator(__p), false);
}
return std::make_pair(_M_insert_unique_node(__bkt, __code, __node), true);
}
因此,尽管我将使用第二种方法(即使需要移动赋值和移动构造函数以及额外的字段),但我想知道为什么emplace创建一个稍后会被忽略的对象是否有充分的理由?也就是说,它是否应该首先检查是否需要创建对象并在已存在时提前退出?
(请注意,对于我的特定情况,默认初始化的项不被认为是有效的,因此问题实际上只涉及emplace)
记录一下,我在23.2.4表102下找到了一些内容:
Effects: Inserts a value_type object t constructed with std::forward<Args>(args)...
if and only if there is no element in the container with key equivalent to the
key of t.
我认为这样可以避免创建对象。
std::map
。对于std::map
,可以在不构造相应对象的情况下查找 _key_。请参见 http://en.cppreference.com/w/cpp/container/map/find。不幸的是,对于std::unordered_map
,这是不可能的。 - nosid