In the interest of clarification: the answers to the amendment are not mistaken. But not one of your first assumptions about adding string&& overload except one detail:
Add
X (std::string&& s) : S(std::move(s)) { }
those. you still need to move , because although s has the declared type of the rvalue reference to string , the expression s , used to initialize s , is an lvalue expression of type string .
In fact, the solution you first proposed (with added movement) is a bit faster than the solution with a transition by value. But both are correct. The pass-by-value solution invokes the line move constructor in extra time when passing the lvalue and xvalue arguments to the X constructor.
In the case of lvalue arguments, the copy is executed anyway, and the string copy constructor is likely to be much more expensive than the line move constructor (except for the lines that fit into the buffer of short lines, in which case moving and copying at about the same speed) .
In the case of xvalue arguments (the value of x is the value of l that was passed to std::move ), solving the step-by-step solution requires two move constructs instead of one. Thus, it is twice as expensive as going through the rvalue reference solution. But still very fast.
The point of this article is to make it clear: bandwidth is an acceptable solution. But this is not the only acceptable solution. Overloading with pass-by-rvalue-ref is faster, but has the disadvantage that the number of overloads required to scale is 2 ^ N as the number of N arguments increases.
Howard Hinnant May 31 '12 at 15:59 2012-05-31 15:59
source share