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
?
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::string
s, 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
.