jeudi 29 octobre 2020

c++ std transform calls copy constructor multiple times

During implementation of a code copying of map elements into a vector I found out that std::transform calls the copy ctor of my custom class multiple times despite of prior vector size reservation. So I compared different ways to do this, and saw that the best method is a simple for-loop. So my question is: are these algorithms really more expensive? If so what is the advantage of them? Or does it not matter for small number of elements? Here my test code:

class A
{
public:
    A() {}
    A(int ai) : i(ai) {}
    A(A& a) : i(a.i) { std::cout << "copy ctor " << i << std::endl; }
    A(const A& a) : i(a.i) { std::cout << "copy const ctor " << i << std::endl; }
    A(A&& a) : i(std::move(a.i)) { std::cout << "move ctor " << i << std::endl; }    
    
    // I removed overloaded operators because they are not called here...

private:
    int i;
};

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;

vec.reserve(m.size());
std::transform(m.begin(), m.end(), std::back_inserter(vec), [](const std::pair<int, A> & p) { return p.second; }); // 3 calls for each ctor

//... clean up and reserve vec
std::for_each(m.begin(), m.end(), [&vec](const std::pair<int, A> & p) { vec.push_back(p.second); }); // 2 calls for each ctor

//... clean up and reserve vec
for (const auto & p : m) // 1 call for each ctor
{
    vec.emplace_back(p.second);
}

Aucun commentaire:

Enregistrer un commentaire