Rvalue reference: Why aren't rvalues implicitly moved?

笑着哭i 提交于 2019-12-12 03:29:39

问题


On Artima article about C++ rvalue reference (http://www.artima.com/cppsource/rvalue.html) there is words: That's why it is necessary to say move(x) instead of just x when passing down to the base class. This is a key safety feature of move semantics designed to prevent accidently moving twice from some named variable.

I can't think situation when such double move can perform. Can you give an example of this? In other words, what will go wrong if all members of T&& would be rvalue references and not just references?


回答1:


Consider this scenario:

void foo(std::string x) {}
void bar(std::string y) {}

void test(std::string&& str)
{
    // to be determined
}

We want to call foo with str, then bar with str, both with the same value. The best way to do this is:

foo(str); // copy str to x
bar(std::move(str)); // move str to y; we move it because we're done with it

It would be a mistake to do this:

foo(std::move(str)); // move str to x
bar(std::move(str)); // move str to y...er, except now it's empty

Because after the first move the value of str is unspecified.

So in the design of rvalue references, this implicit move is not there. If it were, our best way above would not work because the first mention of str would be std::move(str) instead.




回答2:


The way I see it is that if we had some rvalue reference x:

T&& x = ...;

and we called some function using x as a parameter:

f(x)

We need someway to tell f whether or not it can damage x (or "take ownership of x", or "is the last client to use x").

One way to design this would be to qualify every call:

f(yours_now(x)) // ok to damage
f(still_mine(x)) // dont damage

and make the unqualified call illegal.

Another way would be to make one way the default:

Either:

f(yours_now(x)) // ok to damage
f(x) // dont damage

or

f(x) // ok to damage
f(still_mine(x)) // dont damage

So if we agree qualifying every use is too bulky and we should default to one way, which is best? Well lets look at the cost of accidentally picking the default in both cases:

In the first case it was ok to damage, but we accidentally said it wasnt. In this case we lose performance because an unnecessary copy was made, but other than that no big deal.

In the second case it was not ok to damage an object, but we accidentally said it was. This may cause a difficult to detect logical bug in the program, as x is now in a damaged state as f returns, but the author expected it not to be.

So the first case is what was chosen because its "safer".



来源:https://stackoverflow.com/questions/37078582/why-exactly-is-stdmove-needed-on-a-function-parameter-which-is-already-an-rval

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!