c++move-semanticsstdmove

Use of std::move in std::accumulate


In my Fedora 34 environment (g++), std::accumulate is defined as:

template<typename ITER, typename T>
constexpr inline T accumulate(ITER first, ITER last, T init)
{
  for (; first != last; ++first)
      init = std::move(init) + *first; // why move ?

  return init;
}

If the expression init + *first is already an rvalue, what is the purpose of std::move ?


Solution

  • std::move(init) + *first can sometimes generate more efficient code than init + *first, because it allows init to be overwritten. However, since (as you observed) the result of the + will generally be an rvalue, there is no need to wrap the entire expression in a second std::move.

    For example, if you are accumulating std::strings, then std::move(init) + *first might be able to append *first into reserved-but-not-yet-used space in init's buffer instead of having to allocate a new buffer whose length is the sum of the lengths of init and *first.