I've been trying to understand rvalues, lvalues and references and their usage as a returning values of functions (methods) so i created few small examples for practice purpose.
So firstly, i came up with this code (after reading somewhere, possibly here, that whenever i have a "regular" (without reference) return value for some method, it is considered to be rvalue, exception is when i add reference operator sign in the return value, like in this example:
#include <iostream>
int x = 5;
int& References()
{
return x;
}
int main()
{
References() = 3;
std::cout << x;
getchar();
getchar();
}
So here, function References returns lvalue when called, and this code works out just fine, however, since this works, i thought that i can do something similar other way around, and this is what i tried:
#include <iostream>
int x = 5;
int References()
{
return x;
}
int main()
{
int a = References();
std::cout << a;
getchar();
getchar();
}
This code works just fine, the output is 5, which means that i successfully assigned value to the variable a, which is something i expected since this function returns "ordinary" integer so it a rvalue.
HOWEVER, when i once again add reference operator sign to the return value of function References, again, it works fine:
#include <iostream>
int x = 5;
int& References()
{
return x;
}
int main()
{
int a = References();
std::cout << a;
getchar();
getchar();
}
So, even though my function now returns int&
which is returned as lvalue, this code still works and the output is still 5, which means that i managed to assign the value to my variable a successfully. What is going on here? Any help appreciated!
When you use a reference in an expression or an assignment, it evaluates out to what the reference refers to, not the memory address, which I suppose is what you expect to see.
Compare the output of the following functions:
int x = 5;
int& Reference()
{
return x;
}
int *Pointer()
{
return &x;
}
int main()
{
std::cout << Reference() << std::endl;
std::cout << Pointer() << std::endl;
return 0;
}
When you return by reference you have an lvalue
, when you return by value you have a prvalue
. In your case the difference you can read from both of them, but cannot assign to prvalue
, not clear where is your confusion coming from:
int i1 = lvalue; // fine
int i2 = prvalue; // fine
but:
lvalue = 123; // fine
prvalue = 123; // error
closer to your case:
int &func1();
int func2();
int i1 = func1(); // fine
int i2 = func2(); // fine
func1() = 123; // fine
func2() = 123; // error
more info: Value Category
According to https://learn.microsoft.com/en-us/previous-versions/f90831hc(v=vs.140) : You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it.
You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it.
The third example is exactly the same as the second one, it's copying the value. You can copy a value from an lvalue just how you can copy a value from an rvalue. If your a variable was of type int& instead, you wouldn't be copying the actual value, you'd just get the same reference. This might help you understand:
#include <iostream>
int x = 5;
int& References()
{
return x;
}
int main()
{
int a = References();
int& b = References();
std::cout << a; // 5
std::cout << b; // 5
std::cout << x; // 5
a = 6;
b = 7;
std::cout << a; // 6
std::cout << b; // 7
std::cout << b; // 7
getchar();
getchar();
}
For comparison:
int n = 10;
int& r = n;
int* p = &n;
int x = n; // copy by value
int y = r; // copy by value, too, use the variable referenced as source
int z = *p; // copy by value third time, using variable pointed to
int& r0 = r; // copy the reference, i. e. r0 now references n as well
int* p0 = p; // copy the pointer...
n = 12;
// now x, y, z all STILL have value 10!
// r, r0, *p and *p0, in contrast, all yield 12
Not different with functions:
int& ref() { return n; }
int val() { return n; }
int& r1 = ref(); // copy the reference, again r1 references n!
int& r2 = val(); // INVALID!!!
// the latter is comparable to:
int& r3 = 7; // invalid...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.