Binding modifiable rvalue reference to modifiable lvalue
-
13-01-2021 - |
Domanda
I have 3 questions:
Can I bind a lvalue directly to a rvalue reference?
What happens to the object that being
std::move()
?What's the difference between std::move and
std::forward
?
struct myStr{
int m_i;
};
void foo(myStr&& rs) { }
myStr rValueGene()
{
return myStr();
}
int main()
{
myStr mS= {1};
foo(rValueGene()); //ok passing in modifiable rvalue to rvalue reference
// To Question 1:
//below initilize rvalue reference with modifiable lvalue, should be ok
//but VS2010 gives a compile error: error C2440: 'initializing' : cannot convert from 'myStr' to 'myStr &&'
//Is this correct ?
myStr&& rvalueRef = mS;
//by using std::move it seems ok, is this the standard way of doing this
//to pass a lvalue to rvalue reference
//myStr&& rvalueRef = std::move(mS);
// To Question 2:
//also what happens to mS object after std::move ?
//destroyed , undefined ?
}
Soluzione
1>Can I bind a lvalue directly to a rvalue reference ?
Not without an explicit cast (ie: std::move
).
2>What happens to the object that being std::move() ?
Nothing until it is actually moved. All std::move
does is return an r-value reference to what you gave it. The actual moving happens in the move constructor/assignment of the type in question.
3>What's the difference between std::move and std::forward ?
std::move
is for moving; std::forward
is for forwarding. That sounds glib, but that's the idea. If you are intending for an object to be moved, then you use std::move
. If you are intending for an object to be forwarded, you use std::forward
.
Forwarding uses specialized semantics that allow conversions between types of references, so that the reference natures are preserved between calls. The specifics of all of this are very... technical.
std::move
always returns a &&. If you give it an l-value reference, it returns an r-value reference. If you give it a value type, it returns an r-value reference to that value. And so forth.
std::forward
does not always return a &&. Syntactically, std::forward
is just doing a static_cast<T&&>
. However, because of specialized syntax around casting to && types, this cast does not always return a &&. Yes, that's weird, but it solves the forwarding problem, so nobody cares. That's why it's contained in std::forward
, rather than having to explicitly do the static_cast
yourself.
Altri suggerimenti
Question 1. Yes, the compiler is correct.
Question 2. Nothing happens. std::move
just casts things to rvalues.
If however you were to use std::move
to pass mS
(or myStr
) to foo
, then that function might assume that it can "steal" the object and thus mS
might end up in an unspecified state after the function call.