I tried to understand lvalue and rvalue in C++11. So I wrote a test code:
int x = 10;
int foo() { return x; }
int& bar() { return x; }
int&& baz() { return 10; }
int main() {
int& lr1 = 10; // error: lvalue references rvalue
int& lr2 = x; // ok
int& lr3 = foo(); // error: lvalue references rvalue
int& lr4 = bar(); // ok
int& lr5 = baz(); // error: lvalue references rvalue
int&& rr1 = 10; // ok
int&& rr2 = x; // error: rvalue references lvalue
int&& rr3 = foo(); // ok
int&& rr4 = bar(); // error: rvalue references lvalue
int&& rr5 = baz(); // ok
}
It works pretty well, so I inserted std::cout to print results.
#include <iostream>
int x= 10;
int foo() { return x; }
int& bar() { return x; }
int&& baz() { return 10; }
int main() {
int& lr1 = 10; std::cout << lr1 << std::endl; // error
int& lr2 = x; std::cout << lr2 << std::endl; // ok
int& lr3 = foo(); std::cout << lr3 << std::endl; // error
int& lr4 = bar(); std::cout << lr4 << std::endl; // ok
int& lr5 = baz(); std::cout << lr5 << std::endl; // error
int&& rr1 = 10; std::cout << rr1 << std::endl; // ok
int&& rr2 = x; std::cout << rr2 << std::endl; // error
int&& rr3 = foo(); std::cout << rr3 << std::endl; // ok
int&& rr4 = bar(); std::cout << rr4 << std::endl; // error
int&& rr5 = baz(); std::cout << rr5 << std::endl; // ERROR!?
}
int&& rr5 = baz(); std::cout << rr5; causes a Runtime Error, but I don't know why it makes an error.
I think the return value of baz() would be xvalue, so its lifetime is prolonged. But when I tried to access its value, the error occurs. Why?
If you want pass parameter as rvalue reference,use std::move() or just pass rvalue to your function.
By default, the compiler cannot bind a non-const or volatile lvalue reference to an rvalue.
Explanation: If you pass an lvalue T to enqueue , U will deduce to T& , and the forward will pass it along as an lvalue, and you'll get the copy behavior you want. If you pass an rvalue T to enqueue , U will deduce to T , and the forward will pass it along as an rvalue, and you'll get the move behavior you want.
An rvalue reference is formed by placing an && after some type. An rvalue reference behaves just like an lvalue reference except that it can bind to a temporary (an rvalue), whereas you can not bind a (non const) lvalue reference to an rvalue.
I think the return value of
baz()would be xvalue, so its lifetime is prolonged.
At first what baz() returns is always a dangling reference.
For int&& baz() { return 10; }, the lifetime of the temporary is not extended. It's constructed inside the function and will be destroyed when get out of the function, then baz() always returns a dangling reference.
a temporary bound to a return value of a function in a
returnstatement is not extended: it is destroyed immediately at the end of the return expression. Such function always returns a dangling reference.
Then for int&& rr5 = baz();, rr5 is a dangling reference too; deference on it leads to UB and anything is possible.
On the other hand, if you change baz() to return-by-value, everything would be fine; the return value is copied and then bound to rr5, then the lifetime of the temporary is extended to the lifetime of rr5.
LIVE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With