The accepted answer is a good answer (and I supported it). But I wanted to consider this issue in more detail:
The core of my question is: why doesn’t he choose the destination for moving the operator automatically? The compiler knows that v is not used after the job, right? Or does C ++ 11 not require the compiler to be that smart?
This possibility was considered during the development of the semantics of displacement. As a last resort, you might want the compiler to do some static analysis and, if possible, jump from objects:
void set_name(std::string v) { name_ = v; // move from v if it can be proven that some_event is false? if (some_event) f(v); }
Ultimately, requiring such analysis from the compiler is very difficult. Some compilers may do the proof, while others may not. This leads to the fact that the code is not very portable.
So, what about some simpler cases without operators?
void foo() { X x; Y y(x); X x2 = x;
Well, it's hard to see if y.~Y()
noticed by x
. And generally speaking:
void foo() { X x;
it is difficult for the compiler to analyze this to find out if x
is really no longer used after building the copy before x2
.
So, the original “move” sentence gave a rule for implicit moves that were really simple and very conservative:
l Values can be implicitly transferred from cases where copy permission is already permissible.
For instance:
#include <cassert> struct X { int i_; X() : i_(1) {} ~X() {i_ = 0;} }; struct Y { X* x_; Y() : x_(0) {} ~Y() {assert(x_ != 0); assert(x_->i_ != 0);} }; X foo(bool some_test) { Y y; X x; if (some_test) { X x2; return x2; } y.x_ = &x; return x; } int main() { X x = foo(false); }
Here, according to the rules of C ++ 98/03, this program may or may not state, depending on whether elision copying occurs on return x
. If this happens, the program works fine. If this does not happen, the program approves.
And so it was motivated: when RVO is allowed, we are already in an area where there are no guarantees regarding the value of x
. Thus, we should be able to take advantage of this freedom and move from x
. The risk looked small, and the advantage looked huge . This would not only mean that many existing programs would become much faster with a simple recompilation, but it would also mean that now we can return "just move" types from the factory. This is a very big risk advantage.
Later in the standardization process, we got a little greedy and also said that implicit movement occurs when the by-value parameter is returned (and the type corresponds to the return type). The benefits here seem quite large, although the probability of code breaking is slightly larger, since this is not the case when the RVO was (or is) legal. But I have no demonstration of code violation for this case.
So, ultimately, the answer to your main question is that the original design of the semantics of movements took a very conservative route regarding breaking existing code. If this were not so, it would surely have been brought down on the committee. At the end of the process, several changes took place that made the design more aggressive. But by this time the main proposal was firmly established in the standard with the support of the majority (but not unanimous).