My code is as follows:
#include <iostream>
using namespace std;
class A{
public:
void sendByRvalue(string&& str){
cout << str << endl;
}
};
class B{
private:
A a;
void send(string&& str){
a.sendByRvalue(str);
}
public:
void run(const string& str){
send("run " + str + "\n");
}
};
int main(void){
string str("hello world");
B b;
b.run(str);
return 0;
}
When I compile the code shown above, I got some compile errors:
It seems that the str
in B::send
function has been changed to lvalue. Then I change the implement of B::send
, like:
class B{
private:
A a;
void send(string&& str){
cout << boolalpha << is_rvalue_reference<decltype(str)>::value << endl;
a.sendByRvalue(std::move(str));
}
public:
void run(const string& str){
send("run " + str + "\n");
}
};
Everything goes well, but the output of this program made me confuse more. The output is as follows:
Why the parameter str is a rvalue reference but I cannot pass it to the function A::sendByRvalue
directly without std::move
?
str
is a named rvalue reference, which is treated in the language as an lvalue. rvalues are only xvalues or prvalues, and str
is neither.
A note from the standard, on the xvalue rules:
In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether named or not.
struct A {
int m;
};
A&& operator+(A, A);
A&& f();
A a;
A&& ar = static_cast<A&&>(a);
The expressions
f()
,f().m
,static_cast<A&&>(a)
, anda + a
are xvalues. The expressionar
is an lvalue.