The element type in a std::map
is std::pair<const Key, Value>
.
In your example use use std::pair<int, A>
without const, so you need to copy the pair. This adds a copy in the first two solutions. If you change it to std::pair<const int, A>
you can see 2 constructor calls in the first iteration and only one in the second (on par with your for loop).
For the first iteration you now have 1 copy and one move. This is because your lambda needs to copy the A then back_inserter move constructs it into the vector. Normally I wouldn’t worry about an extra move since they are supposed to be cheap.
However, you can get rid of it. We can force the lamba to not copy the A instance, by ,for example, specifying the return type to be a reference. So now the back_inserter will have to copy when it inserts, but that’s it.
This version of your code does one copy per element for each solution:
std::map<int, A> m; m.insert(std::make_pair(0, A(7))); m.insert(std::make_pair(1, A(3))); m.insert(std::make_pair(2, A(1))); std::vector<A> vec;
std::cout << "Transform" << std::endl;
vec.reserve(m.size());
std::transform(m.begin(), m.end(), std::back_inserter(vec),
// changed the key type and return type.
[](const std::pair<const int, A> & p)->const A& { return p.second; });
std::cout << "for_each" << std::endl;
vec.resize(0);
vec.reserve(m.size());
std::for_each(m.begin(), m.end(),
// changed the key type.
[&vec](const std::pair<const int, A> & p) { vec.push_back(p.second); });
std::cout << "START\n";
vec.resize(0);
vec.reserve(m.size());
for (const auto & p : m) {
vec.emplace_back(p.second);
}
CLICK HERE to find out more related problems solutions.