Expressions are always evaluated at the point the program reaches them. The result of an expression is always a value (or void).
Values have a type, and expressions have a value category, which combine to choose which overload of an overload set is used, at any particular use.
In your case, string operator+(...)
results in a string value, with the category pr-value (which is a type of rvalue). It is then immediately bound to a string&&, so it's lifetime is extended to that of the reference.
If you had instead assigned it to a plain string, string& string::operator=(string&&)
would have been chosen over any other overloads of that operator. Note that since c++11 the compiler is allowed (and from c++17 required) to materialize the value directly inside the target object. This process is known as copy/move elision or (N)RVO, for (Named) Return Value Optimisation.
s2
was just anotherstd::string
, the results will be the same, but would the resulting binaries be any different? – Stromboli