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
return
statement 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