c++ - std::unordered_map::emplace object creation -
i in process of selecting 1 of 2 methods of putting things 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);
i did experiments see 1 perform better find when inserting unique elements, behaviour (as in efficiency) equivalent.
however, in case of inserting duplicate items, , consider construction of value or differentvalue not trivial, surprised find emplace constructs object regardless of whether insert or not.
so, second method seems win far in case since default constructor has isdefaultinitialized_(true) in there , not more.
for emplace, code seems be:
... _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); }
so, although i'm going go second method (even if requires move assignment , move constructors , fields), wondering there rationale why emplace creates object later disregards? is, should first check if needs create object , out if exists?
(note particular case default initialized items not considered valid, question emplace)
for record, found under 23.2.4 table 102:
effects: inserts value_type object t constructed std::forward<args>(args)... if , if there no element in container key equivalent key of t.
which think allow not creating object.
in opinion, quoted part standard misleading, because suggests, object constructed if there no matching element in container. guess trying state:
effects: constructs
value_type
objectt
std::forward<args>(args)...
. inserts constructed objectt
if , if there no such element in container key equivalent key oft
.
the reason is: implementation of function emplace
has construct t
in order find out if element equivalent key exists, because implementation has invoke hash function , equals predicate. however, in general can invoked objects of type value_type
, not tuples used construct these objects.
in theory, possible specify emplace function, doesn't construct t
if there element equivalent key. interestingly, similar added c++14 std::map::find
. see following documentation:
there 2 overloads, can used arbitrary types, long compare function fulfills additional requirements. interestingly enough, there no such overload std::unordered_map
.
Comments
Post a Comment