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
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.
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.
The keys are automatically sorted in a strict-weak ordering.
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.
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>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With