Is a member of an rvalue structure an rvalue or lvalue?
A member of an rvalue expression is an rvalue.
The standard states in 5.3.5 [expr.ref]:
If E2 is declared to have type
“reference to T”, then E1.E2 is an
lvalue [...]
- If E2 is a non-static data member, and the type of E1 is “cq1 vq1 X”, and
the type of E2 is “cq2 vq2 T”, the
expression designates the named member
of the object designated by the first
expression. If E1 is an lvalue, then
E1.E2 is an lvalue.
Is (*&a) a lvalue or a rvalue?
Per C 2018 6.5.3.2 4 (discussing the unary *
operator), the result of unary *
is an lvalue:
… If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object.…
This tells us that *&a
is an lvalue. However, the expression asked about in the question is (*&a)
, so we must consider the effect of the parentheses.
6.3.2.1 2 (discussing automatic conversions) seems to tell us that (*&a)
is converted to the value in *&a
and is not an lvalue:
Except when it is the operand of the sizeof operator, the unary
&
operator, the++
operator, the--
operator, or the left operand of the.
operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion.
However, 6.5.1 5 (discussing parenthesized expressions) contradicts this:
A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.
This is a defect in the C standard; 6.5.1 5 and 6.3.2.1 2 contradict each other. It is left to us to understand that 6.5.1 5, which is specifically about parenthesized expressions, takes precedence over the more general 6.3.2.1 2, and this is how all C implementations behave.
Thus (*&a)
is an lvalue.
Return the kind of an expression in C, i.e., whether it's an rvalue or lvalue
According to the C Standard, section 6.3.2.1:
An lvalue is an expression (with an object type other than void) that potentially designates an object.
Although this is rather vague, it continues with
The name ‘‘lvalue’’ comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue.
And further more
What is sometimes called ‘‘rvalue’’ is in this International Standard described as the ‘‘value of an expression’’.
What this means to me is
An lvalue is a value that supports assignment and is on the left side of the assignment operator.
An rvalue is any value not on the left hand side of the assignment operator.
So for example
#include <stdio.h>
int main() {
int array[1], *pointer, i = 42;
// ^ ^-rvalue
// lvalue
*array = i;
// ^ ^-rvalue
//lvalue
pointer = array;
// ^ ^-rvalue
//lvalue
printf("%p\t%d\n", pointer, *pointer);
// ^-rvalues-^
// causes segfault but compiles:
*(int *)4 = 2;
// ^ ^-rvalue
// lvalue
return 0;
}
As above in the comments and to answer the question fully
You'd have to use a compiler that lets you access the AST of a given compilation unit.
C++ does reference return a lvalue or rvalue?
In this context &
is the address-of operator. The value of &b
is a pointer of type int *
. It is a prvalue. This is unrelated to use of the &
symbol in a declaration (where it means the declaration of a reference) -- symbols mean different things in declarators than they do in expressions.
You cannot change the address of a variable. Variables have the same address for their whole lifetime.
why the type of obj.i and std::forward<int>(obj.i) are different?
You're actually forwarding the wrong thing. In this function:
void foo(Obj &&obj)
{
foo(std::forward<int>(obj.i));
foo(obj.i);
}
obj
has name, so it's an lvalue. obj.i
is an lvalue in both cases, just in the first you're explicitly casting it to an rvalue! When forward
gets a reference type, you get out an lvalue. When it gets a non-reference type, you get an rvalue. You're giving it a non-reference type, so the forward
here is equivalent to: foo(std::move(obj.i));
Does that make it clearer why you get an rvalue?
The question you linked, however, is about members of rvalues. To get that, you need to turn obj
itself into an rvalue:
foo(std::move(obj).i);
Here, since std::move(obj)
is an rvalue, std::move(obj).i
is an rvalue as well.
Regardless, using forward
when taking an argument by not-forwarding-reference is a little weird. Here's a more general example:
template <class O>
void foo(O&& obj) {
foo(std::forward<O>(obj).i);
}
foo(obj); // calls foo(int&)
foo(std::move(obj)); // calls foo(int&&)
In the former case, std::forward<O>(obj)
is an lvalue because O
is Obj&
, which makes std::foward<O>(obj).i
an lvalue. In the latter case, they're both rvalues.
Why rvalue reference member would be const?
Why rvalue reference member would be const?
Don't assume that it's const
. You should assume that unique_ptr(const unique_ptr&)
is merely the best match, from the available constructors.
Because in constructor
temp
is a rvalue reference
Surprise! It is not an r-value reference.
The variable temp
is bound to an r-value, when the constructor is called. And now that it's a named variable, it's no longer a "temporary". It has become an l-value.
Since you know that the value was an r-value when the constructor was called, you can safely move the members, converting them back to an r-value.
C(C &&temp)
: mVector(std::move(temp.mVector))
// ^^^^^^^^^ We know that temp CAME FROM an r-value,
// so it can safely be moved.
, mSize(temp.mSize)
{}
Related Topics
Why Gcc Does Not Use Load(Without Fence) and Store+Sfence for Sequential Consistency
Virtual Destructor: Is It Required When Not Dynamically Allocated Memory
In C++, Differencebetween a Method and a Function
How to Quickly Enumerate Directories on Win32
Is It a Good Practice to Use Unions in C++
Creating a String List and an Enum List from a C++ MACro
C++ Linux Double Destruction of Static Variable. Linking Symbols Overlap
Preventing Non-Const Lvalues from Resolving to Rvalue Reference Instead of Const Lvalue Reference
Copy a Std::Vector to a Repeated Field from Protobuf with Memcpy
How to Use a C++11 to Program the Arduino
Should Accessors Return Values or Constant References
What Optimization Does Move Semantics Provide If We Already Have Rvo
Using C++11 Range-Based for Loop Correctly in Qt
Propagate Constness to Data Pointed by Member Variables