szli
szli

Reputation: 39119

Avoid unnecessary constructor calls while inserting element to std::unordered_map?

Say I have std::unordered_map < int, std::vector< int > > my_hashtable and I insert a new entry:

my_hashtable.insert(make_pair(a_key, std::vector()));

This works but it invokes constructors and assignment ops multiple times. (1) std::vector(), (2) make_pair arguments are pass by value, copy (3) make_pair return type by value, copy again (4) function insert will make copy again.

Please correct me if I count it incorrectly.

Hence, we are making too many copies, we really only should call constructor once, how can we achieve that (under C++11)?

I noticed that std::unordered_map::insert has a version working with move constructor, but not sure how to use that.

Upvotes: 3

Views: 1752

Answers (2)

user2249683
user2249683

Reputation:

The problem is the signature of the value_type of the map: It is std::pair<map::key_type, map::mapped_type> where the key type is const qualified.

This will eliminate a copy/move:

typedef std::unordered_map < int, std::vector< int > > hash_table:
my_hashtable.insert(hash_table::value_type(a_key, std::vector()));

The signature of the result of make_pair in your example is likely std::pair<int, vector<...> > and not std::pair<const int, vector<...> >

Upvotes: 2

iavr
iavr

Reputation: 7647

You can check the examples of std::unordered_map::emplace():

my_hashtable.emplace(
   std::piecewise_construct,
   std::forward_as_tuple(a_key),
   std::forward_as_tuple()
);

Here, there is no unnecessary constructor call.

Upvotes: 2

Related Questions