Code
#include<iostream>
int main()
{
int a=3;
a++=5;
std::cout<<a;
}
Output (as expected)
[Error] lvalue required as left operand of assignment
1. The post increment operator (a++) has the highest priority in the table. So it will definitely execute before the assignment operator (=). And as per the rule of post increment the value of variable a will increment only after execution of that statement.
So what exactly happens when the post increment operator (++)
executes before the assignment operator (=)?
2.
In C both the pre- and post-increment operators yield rvalues but C++ updated the pre-increment operator to an lvalue while keeping the post-increment operator as an rvalue only. The reason for that is we can't make it an lvalue as it possesses only the old value, not the updated one. But I don't understand this reason properly.
See now a++ has the rvalue 3, not the variable itself, right? But what if it brings a variable which possesses an lvalue, then 5 will insert into that and after the end of the statement its value will be 6. What's the problem with this and why can't it be done?
And As per rule of post increment the value of variable a will increment only after execution of that statement.
That's a bit misleading. The variable is incremented immediately. But the result of the expression is the old value. This should make it easier to understand why it cannot be an lvalue. The modified object doesn't have the old value, so the hypothetical lvalue cannot refer to that object. The value is a new, temporary object; it is a prvalue.
As an analogy, think about writing a function that does the same thing as post increment. This is how it would be written (if you define overloaded operator overload for a class, then a function such as this is quite literally what you'd write with a few changes):
int post_increment(int& operand)
{
int old = operand;
operand += 1;
return old;
}
How could you meaningfully re-write that function to return an lvalue (reference) and still have the behaviour expected from the post increment?
Related
The prefix operators return the object
itself as an lvalue. The postfix operators return a copy of the object’s original value
as an rvalue.
so in a statement like so *a++ a is being incremented and a copy of the original value of a is returned as rvalue but from the microsoft c++ language reference on Lvalues and Rvalues
An rvalue is a temporary value that does not persist beyond the expression that uses it
and gives an example
// lvalues_and_rvalues1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
int x = 3 + 4;
cout << x << endl;
}
In this example, x is an lvalue because it persists beyond the expression that defines it. The expression 3 + 4 is an rvalue because it evaluates to a temporary value that does not persist beyond the expression that defines it.
My questions:
1) what is the rvalue being returned from the *a++ so that it can be dereferenced?
2) Did i misunderstand any concept ?
Thanks in advance!
The prefix operators return the object itself as an lvalue. The postfix operators return a copy of the object’s original value as an rvalue.
Wrong! Well, mostly. If the quote is talking about all prefix/suffix operators, then it's completely errated. However, if it's talking about the ++ and -- prefix/postfix pairs, then it's correct.
Now, taking that into account...
what is the rvalue returning from the *a++ so that it can be dereferenced?
Assuming a is a pointer of some kind, a++ increments a and yields a rvalue consisting of a's value before the increment. The increment and decrement operators, ++ and --, in both postfix and prefix forms, require an lvalue as their operator. This is because rvalues are temporary, that is, their scope is limited by the expression their occur in, so these operators make little or no sense on them. Remember, these operators not only inspect/read, but change/write to the variable itself.
The unary * operator takes a pointer(-like) object and dereferences it, yielding an lvalue found in there. It works for both rvalue and lvalue pointers. This is because * can be considered sort of a "passive" operator. It does not change/write to the pointer itself, but dereferences it and returns the lvalue object at the address stored by the pointer, whose address is of course that contained by the pointer. As all that * needs is the memory address contained in a pointer object, and the address of the pointer itself, if it has one at all, is useless here, * makes sense for both rvalues and lvalues.
You can think that * "requires an rvalue", and that "lvalues can be used as rvalues when necessary", if it clarifies (or confuses?) things a little bit more.
*a++ is equivalent to:
auto temp = *a;
a++;
// Use the value of temp here
except you can only refer to the value once, where as temp you could refer to multiple times.
Say I was reading data in which the indexing starts at 1. I want my indexing to be 0 based.
Why is it not acceptable to use postfix increment/decrement operators after a stream insertion operator?
int a;
std::cin >> a--;
The result of a post-increment operator is a temporary object, even if the increment is strictly applied only at the end of the expression. To read a value, an lvalue is needed but temporary objects aren't lvalues: they are bound to go away. Note, that you'd also read the value into the temporary, retaining an unspecified value in a.
operator>> has an overload that takes a int&. The result of a-- is an rvalue, and you can't bind a non-const reference to an rvalue.
I noticed in C++ that something like++++i is allowed and increments i by 2. However, i++++ is not allowed. Why is the latter not allowed whereas the former is?
The result of postfix ++ is a prvalue. Postfix ++ can only be applied to modifiable lvalue. So you can't apply postfix ++ to the result of another postfix ++. This makes sense because it needs some object to modify. The result of the operator is just a value (a copy of the original value of the operand) - there's no object for you to modify.
On the other hand, the result of prefix ++ is an lvalue and it also expects an lvalue as its operand. Therefore you can pass the result of a prefix ++ to another ++.
It might help for you to think about lvalues as denoting objects in memory and rvalues as just values (that may have come from an object in memory). Postfix ++ expects an lvalue because it wants an object that it can modify. It returns an rvalue because the result is just a value not associated with any object (because it was copied from the operand before modification). Prefix ++ also wants to modify its operand, so also expects an lvalue. However, it returns the object after modification, which is the operand object itself and so its result is an lvalue too.
Consider the following code snippet
int a,i;
a = 5;
(i++) = a;
(++i) = a;
cout<<i<<endl;
Line (++i) = a is compiling properly and giving 5 as output.
But (i++) = a is giving compilation error error: lvalue required as left operand of assignment.
I am not able to find the reason for such indifferent behavior. I would be grateful if someone explains this.
The expression i++ evaluates to the value of i prior to the increment operation. That value is a temporary (which is an rvalue) and you cannot assign to it.
++i works because that expression evaluates to i after it has been incremented, and i can be assigned to (it's an lvalue).
More on lvalues and rvalues on Wikipedia.
According to the C++ standard, prefix ++ is an lvalue (which
is different than C), post-fix no. More generally, C++ takes
the point of view that anything which changes an lvalue
parameter, and has as its value the value of that parameter,
results in an lvalue. So ++ i is an lvalue (since the
resulting value is the new value of i), but i ++ is not
(since the resulting value is not the new value, but the old).
All of this, of course, for the built-in ++ operators. If you
overload, it depends on the signatures of your overloads (but
a correctly designed overloaded ++ will behave like the
built-in ones).
Of course, neither (++ i) = a; nor (i ++) = a; in your
example are legal; both use the value of an uninitialized
variable (i), which is undefined behavior, and both modify i
twice without an intervening sequence point.
In C++, pre-increment operator gives lvalue because incremented object itself is returned, not a copy.
But in C, it gives rvalue. Why?
C doesn't have references. In C++ ++i returns a reference to i (lvalue) whereas in C it returns a copy(incremented).
C99 6.5.3.1/2
The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation. The expression ++Eis equivalent to (E+=1).
‘‘value of an expression’’ <=> rvalue
However for historical reasons I think "references not being part of C" could be a possible reason.
C99 says in the footnote (of section $6.3.2.1),
The name ‘‘lvalue’’ comes originally
from the assignment expression E1 =
E2, in which the left operand E1 is
required to be a (modifiable) lvalue.
It is perhaps better considered as
representing an object ‘‘locator
value’’. What is sometimes called
‘‘rvalue’’ is in this International
Standard described as the ‘‘value of
an expression’’.
Hope that explains why ++i in C, returns rvalue.
As for C++, I would say it depends on the object being incremented. If the object's type is some user-defined type, then it may always return lvalue. That means, you can always write i++++++++ or ++++++i if type of i is Index as defined here:
Undefined behavior and sequence points reloaded
Off the top of my head, I can't imagine any useful statements that could result from using a pre-incremented variable as an lvalue. In C++, due to the existence of operator overloading, I can. Do you have a specific example of something that you're prevented from doing in C, due to this restriction?