I'm trying to understand this code but I can't figure out why this version
for (; first != last; ++first)
init = std::move(init) + *first;
is faster than this
for (; first != last; ++first)
init += *first;
I did take them from std::accumulate. The assembly code of the first version is longer than the second one. Even if the first version create an rvalue ref of init, it always create a temp value by adding *first and then assign it to init, that is the same process in second case where it create a temp value and then assign it to init. So, why using std::move is better than "append value" with the += operator?
EDIT
I was looking at the code of C++20 version of accumulate, and they say that before C++20 accumulate was this
template<class InputIt, class T>
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = init + *first;
}
return init;
}
and after C++20 it become
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
I've just wanted to know, if by using std::move there was any real improvement or not.
EDIT2
Ok, here is my example code:
#include <utility>
#include <chrono>
#include <iostream>
using ck = std::chrono::high_resolution_clock;
std::string
test_no_move(std::string str) {
std::string b = "t";
int count = 0;
while (++count < 100000)
str = std::move(str) + b; // Without std::move
return str;
}
std::string
test_with_move(std::string str) {
std::string b = "t";
int count = 0;
while (++count < 100000) // With std::move
str = str + b;
return str;
}
int main()
{
std::string result;
auto start = ck::now();
result = test_no_move("test");
auto finish = ck::now();
std::cout << "Test without std::move " << std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count() << std::endl;
start = ck::now();
result = test_with_move("test");
finish = ck::now();
std::cout << "Test with std::move " << std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count() << std::endl;
return 0;
}
If you run it you notice that the std::move version is really faster than the other one, but if you try it using built-in types you get the std::move version slower than the other one.
So my question was, since this situation is probably the same of std::accumulate, why do they say the C++20 accumulate version with std::move is faster than the version without it? Why using std::move with something like strings I get an improvement like that, but not using something like int? Why all of this, if in both of cases, the program create a temporary string str + b (or std::move(str) + b) and then move to str? I mean, it is the same operation. Why is the second faster?
Thanks for patience. Hope I made myself clear this time.