Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving keys from unordered_map

I've searched but I only found questions about move constructor with the mapped value, but I want to try something different.

Is it possible to use std::move the key from a std::unordered_map? The reason is quite simple: I'd like to construct an example where I create a vector from the map, wasting as little as possible of memory. I know it would mess up with the representation of the map, but hey, after all I will never use the map again, so it would make sense to move values out.

My guess is this: no, I cannot do that. However, I'd like some confirmation.

Here's a simple code. I expected to see the move constructor called, but I have the copy constructor called.

Cheers & Thanks!

#include <iostream>
#include <unordered_map>
#include <vector>
#include <string>
#include <utility>

class prop
{
public:
    prop(const std::string &s, int i) : s_(s), i_(i) { std::cout << "COPIED" << std::endl; };

    prop(std::string &&s, int i) : s_(std::move(s)), i_(i) { std::cout << "MOVED" << std::endl; };

    std::string s_;
    int         i_;
};

std::string gen_random(const int len) {
    static const char alphanum[] =
    "ABC";

    std::string s;
    s.resize(len);

    for (int i = 0; i < len; ++i) {
        s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
    }

    return s;
}

int main()
{
    const long n = 3, len = 4, max = 20;

    std::unordered_map<std::string, int> map;

    std::cout << ">>GENERATING" << std::endl;
    for (int i = 0; i < n; i++) map[gen_random(len)]++;

    if (map.size() < max)
    {
        std::cout << ">>MAP" << std::endl;
        for (auto &p : map) std::cout << p.first << " : " << p.second << std::endl;
    }

    std::cout << ">>POPULATING VEC" << std::endl;
    std::vector<prop> vec;
    vec.reserve(map.size());
    for (auto &p : map) vec.push_back(prop(p.first, p.second));

    if (map.size() < max)
    {
        std::cout << ">>VEC" << std::endl;
        for (auto &p : vec) std::cout << p.s_ << " : " << p.i_ << std::endl;
        std::cout << ">>MAP" << std::endl;
        for (auto &p : map) std::cout << p.first << " : " << p.second << std::endl;
    }

    std::cout << ">>POPULATING MOV" << std::endl;
    std::vector<prop> mov;
    mov.reserve(map.size());
    for (auto &p : map) mov.push_back(prop(std::move(p.first), p.second));

    if (map.size() < max)
    {
        std::cout << ">>MOV" << std::endl;
        for (auto &p : mov) std::cout << p.s_ << " : " << p.i_ << std::endl;
        std::cout << ">>MAP" << std::endl;
        for (auto &p : map) std::cout << p.first << " : " << p.second << std::endl;
    }

    return 0;
}

output

>>GENERATING
>>MAP
CBAC : 1
BCAC : 1
BBCC : 1
>>POPULATING VEC
COPIED
COPIED
COPIED
>>VEC
CBAC : 1
BCAC : 1
BBCC : 1
>>MAP
CBAC : 1
BCAC : 1
BBCC : 1
>>POPULATING MOV
COPIED
COPIED
COPIED
>>MOV
CBAC : 1
BCAC : 1
BBCC : 1
>>MAP
CBAC : 1
BCAC : 1
BBCC : 1
Program ended with exit code: 0
like image 747
senseiwa Avatar asked Nov 21 '13 08:11

senseiwa


People also ask

Does unordered_map store the key?

unordered_map is an associated container that stores elements formed by the combination of a key value and a mapped value. The key value is used to uniquely identify the element and the mapped value is the content associated with the key.

How do you change the key of an unordered map?

You can use unordered_map::erase and unordered_map::insert to update a key. The average time complexity is O(1)(BTW, the worst is O(n)). If you are using C++17, you can also use unordered_map::extract to update a key.

Are Keys sorted in unordered_map?

The keys are automatically sorted in a strict-weak ordering.

What is faster than unordered_map?

Insertion of spread keys in std::map tends to outperform std::unordered_map when map size is under 10000 elements. Insertion of dense keys in std::map doesn't present performance difference with std::unordered_map under 1000 elements. In all other situations std::unordered_map tends to perform faster.


1 Answers

You cannot move, keys will be copied, since

value_type  std::pair<const Key, T>

http://en.cppreference.com/w/cpp/container/unordered_map so, here

for (auto &p : map)

p will be deduced to std::pair<const std::string, int>.

like image 199
ForEveR Avatar answered Sep 18 '22 00:09

ForEveR