LeastSquaresWonderer
LeastSquaresWonderer

Reputation: 530

Dereferencing a pointer while passing to a reference expecting function creates a copy, why?

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);
}

Question

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.

Answer

@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

Answers (1)

Benjamin Barrois
Benjamin Barrois

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

Related Questions