Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using const char* as key for map/unordered_map

How to create map/unordered_map that will use const char* as key directly?

If I use map<std::string,..>, then on each resolving map["abc"] = ... a new std::string object will be created. That causes a big overhead for allocating memory, creating a string object and copying the string into it.

How do I declare a map object that uses const char* directly without any overhead?

like image 385
nik Avatar asked May 30 '18 15:05

nik


People also ask

How are keys stored in unordered_map?

unordered_map vs map In unordered_map, the keys are stored in any order. A map has a balanced tree structure implementation which is the reason it is possible to maintain order between elements. The average time complexity, however, for unordered_map operations is O(1) and O(log n) for map operations.

Can unordered map have same keys?

We have discussed unordered_map in our previous post, but there is a limitation, we can not store duplicates in unordered_map, that is if we have a key-value pair already in our unordered_multimap and another pair is inserted, then both will be there whereas in case of unordered_map the previous value corresponding to ...

How do I make my unordered map faster?

reserve(1024); mp. max_load_factor(0.25); With this two lines unordered_map become about 10 times faster. You can replace 1024 with another suitable power of two.

How do you pass an unordered map in a function?

Just replace the int with something like unordered_map<int, int> . You're going to want to pass it with a const reference if you don't need to modify it. Don't use the const if you want to modify the original object that was used to call the function. Save this answer.


2 Answers

You can use a std::string_view:

std::map<std::string_view, int> Map;
Map["abc"] = 1; // no allocation necessary to store "abc"

It is basically a wrapper around string objects. And it's a view, which means that it doesn't own the string and thus doesn't copy and allocate memory to store a string.

Note that for small strings (and also literals), std::string doesn't allocate too due to SSO and so the overhead is minimal. Always measure before optimizing.

like image 122
Rakete1111 Avatar answered Sep 20 '22 13:09

Rakete1111


As an alternative to Rakete1111's string_view answer, you can equip your map with a suitable comparator (and hasher, for the unordered_map):

struct LesserString
{
  bool operator() (const char *lhs, const char *rhs) const
  {
    return std::strcmp(lhs, rhs) < 0;
  }
};

struct HashString
{
  std::size_t operator() (const char *arg) const
  {
    return however_you_want_to_hash_the_string();
  }
};

struct EqualString
{
  bool operator() (const char *lhs, const char *rhs) const
  {
    return !strcmp(lhs, rhs);
  }
};

std::map<const char*, WhateverValue, LesserString> m1;
std::unorderd_map<const char*, WhateverValue, HashString, EqualString> m2;
like image 29
Angew is no longer proud of SO Avatar answered Sep 20 '22 13:09

Angew is no longer proud of SO