Reputation: 530
Consider a simple example
template<class InputIterator,class InputIterator2, class OutputIterT, class Function, class T2>
OutputIterT foo(InputIterator first, InputIterator2 last, OutputIterT result, Function fn, const T2& x)
{
while (first!=last) {
*result=fn(*first,x);
++first;
}
return result;
}
where the Function fn that is passed is
template<class T, class V>
T fn(const T& a, const V& b) {
return std::make_pair(a.first, a.second *b);
}
When I use this code and check for the constructors being called, I see that at each call fn(*first,x), the copy constructor is being called. I find this hard to understand, as the function parameter is a reference. Please note that the iterators being used, are map iterators. To avoid the unnecessary copy I changed the code to accept the iterator directly (fn function), so that the line now is
*result=fn(first,x);
and the fn is
template<class Iter, class V>
T fn(Iter a, const V& b) {
return std::make_pair(a->first, a->second *b);
}
Why is the copy being created in the first case, with the call to fn? When can this happen? Why does it happen, even though the function parameter is a const reference? Thank you for helping me understand.
To clarify, the copy constructor of the
(*first).second
is being called, before entering the function fn.
@IgorTandetnik provided the correct answer in the comments bellow, and @SebastianRedl provided further rational on why this happens.
The map object of the type
map<Key,Value>;
is really
map<Key const,Value>;
even if the programmer does not specify it as such (if you omit the const).
Now, when instantiating the foo function, if you (as I did) provide the pair type as
pair<Key,Value>
this does not match the pairs contained in the map, which are
pair<Key const, Value>
(again, even if you did not explicitly say key should be const). This causes a need for conversion as when passing to the function fn.
Thank you both!
Upvotes: 0
Views: 217
Reputation: 2686
I think the copy is made in std::make_pair()
method, which returns a reference to a new object composed of two instances of the class T and V that are copied from a->first
and a->second *b
. Else, modifying anything in the returned pair would also modify the object you passed by reference in fn()
.
edit: now you have given more information, I think the copy constructor of (*first).second is called when you are performing : a->second *b
. As I don't know how is overloaded your operator *, I guess it implies a copy.
Upvotes: 1