Don't let expiring values go to waste.
Or an example of case when it's useful to have std::move in return.
Because of the way std::move can interfere with RVO due to pessimization, inexperienced C++ programmers are sometimes afraid to use std::move for returned instances. Such broad rules are rarely useful and in some cases are harmful as they cover instances that have nothing to do with RVOs.
Let’s take a look at
for example. To understand what’s going on, we’ll use the following setup
Since copyFrom uses a copy of opt_trace, it seems wasteful to perform one more copy of a trace for returned instance. Unfortunately, that’s exactly what would happen
We can avoid this unnecessary copy by marking opt_trace as expired using std::move
or explicitly moving returned value
both of which produce identical assembly
I’ve intentionally used * operator to remove extra checks that optional::value() performs, but it’s obviously equally useful in both cases.
Most of the time I see this missed performance opportunity when it comes to builders. Properly designed builders use ref modifiers to provide build methods with rvalue modifier, but developers often forget to std::move builder instance before calling its build function when it comes to use-cases with conditionals. For example,
is used instead of