You should prefer passing by value if you are going to make a copy with immutable values. For example, your version of const& WriteDefaultFileOutput explicitly copies this parameter, and then moves the copy with the move version. This means that if WriteDefaultFileOutput is called with a movable value (xvalue or prvalue), then it will be moved, and if it calls with lvalue, it will be copied.
This means that there is no difference between the two forms of this function. Consider this:
WriteDefaultFileOutput(L"SomeString");
In your first case, it will create a temporary wstring . Prvalues ββare times, so it will be "moved" to the parameter (since wstring has a move constructor). Of course, any compiler that deserves its salt will override the course and simply build a temporary value directly in the parameter.
In your second case, more or less the same thing happens. A temporary wstring . Prvalues ββare times, so they can bind to && types. Therefore, it will call the first version of your function using the r-value reference to a temporary one. The only possible difference would be from a compiler that cannot overcome the move. And even then, traffic is not so expensive (depending on your implementation of basic_string ).
Now consider the following:
std::wstring myStr{L"SomeString"}; WriteDefaultFileOutput(myStr);
In the first case, a call to WriteDefaultFileOutput will copy the value of myStr into the function parameter.
In the second case, myStr is the value of l. It cannot be attached to the && parameter. Therefore, the only version that he can name is the const& version. This function will manually create a copy, and then move the copy from another.
Identical effect. Your first version has less code, so for obvious reasons.
In general, I would say that there are only two reasons to accept the parameter as && :
- You are writing a move constructor.
- You are writing a forwarding function and should use perfect forwarding.
In all other cases, when you want movement to be possible, just take the meaning. If the user wants to copy, let them be copied. I believe that if you want to explicitly prohibit copying a parameter, you can take && . But the main problem is clarity.
If you take a value parameter and the user provides a roaming value, then the value provided by the user will always be roaming. For example, your version of && WriteDefaultFileOutput should not actually move data from its parameter. It certainly can. But this is optional. If he accepted the value, then he would already have declared the data.
Therefore, if a function takes a parameter of a value, and you see std::move at that value, then you know that the moved object is now empty. It is guaranteed to be ported from.