I am having confusion with the return value of post-increment and pre-increment operator.Whether it returns r-value or l-value.
#include<iostream>
using namespace std;
int main(){
int a=10;
cout<<++a++<<"\n";
}
The following code give a compile error.
error: lvalue required as increment operator
Why is there an error?
How does the compiler evaluates the expression ++a++?
The result of the post-increment expression, a++ is an rvalue; a temporary with the value that a had before incrementing. As an rvalue, you can use its value, but you can't modify it. Specifically, you can't apply pre-increment it, as the compiler says.
If you were to change the precedence to do the pre-increment first:
(++a)++
then this would compile: the result of pre-increment is an lvalue denoting the object that's been modified. However, this might have undefined behaviour; I'm not sure whether the two modifications and the various uses of the value are sequenced.
Summary: don't try to write tricky expressions with multiple side-effects.
Conceptually, the postfix ++ has higher precedence than prefix ++.
So a++ will be computed first. But this is not an lvalue (as it's the previous value of a). It therefore cannot be pre-incremented. Hence the compiler output.
More importantly though, the behaviour of the whole expression ++a++ is undefined due to their being no sequencing point in the expression.
Just for what it's worth (not much, IMO) if you make the a in question the proper type, it's possible to get this to compile and have defined behavior. The trick (and in this case it's a dirty, evil trick) is to overload the post-fix increment operator to return an lvalue:
class dirty_evil_trick {
int val;
public:
dirty_evil_trick() : val(0) {}
// to demonstrate, I'll just make postfix increment act like prefix increment.
dirty_evil_trick operator++(int) {
++val;
return *this;
}
dirty_evil_trick operator++() {
++val;
return *this;
}
operator int(){ return val; }
};
As implied by the name, this is (at least in my opinion) truly horrible code. We've made both the prefix and postfix increment operators act like prefix increment. So, for example, if we exercise it as follows:
int main(){
dirty_evil_trick a;
std::cout << ++a++;
}
...it should print out 2. And, since invoking the operator overload functions imposes ordering constraints, we should be able to count on that result with all conforming compilers.
I'll repeat once more though: this is not intended as advice about how you should write code. It's really just a demonstration of what the error message you got meant, and how you can write code that does let this actually work (or, at least compile and do something. Whether that qualifies as "working" is a whole 'nother question).
First of all, that's terrible programming style. Depending on your needs, you can easily write:
++a;
cout << a++ <<"\n";
or
a++;
cout << ++a <<"\n";
Coming to the compiler error...
Due to operator precedence, ++a++ is the same as ++(a++). However, a++ evaluates to an rvalue. Using the prefix increment operator on an rvalue is not allowed. That will be analogous to using ++10, which is not legal.
Related
I have just got the following warning from clang-tidy:
overloaded "operator++" returns a non-constant object
instead of a constant object type
https://clang.llvm.org/extra/clang-tidy/checks/cert-dcl21-cpp.html
Unfortunately the link which they are providing there does not work and https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682 has no easy way to find exactly this rule (seemingly the DCL rules start from 50).
But regardless where I look in the standard (for ex 16.5.7 Increment and decrement [over.inc]), I find no reference that postfix operator ++ should return a const:
struct X {
X operator++(int); // postfix a++
};
Question: is just clang-tidy overly protective, erroneous or why would I want to declare the return type of the postfix to be const?
It's clang-tidy trying to stop you from writing code that accomplishes nothing:
(x++)++; // Did we just increment a temporary?
Such forms of overloading may be useful, but not usually for postfix ++. You have two options:
Do as clang-tidy says, but then maybe lose the benfeits of move semantics.
lvalue ref-qualify the overload instead, to mimic the little ints.
X operator++(int) &; // Can't apply to rvalues anymore.
Option 2 is superior; prevents those silly mistakes, and retains move semantics if applicable.
I want to use ternary operator("? : ") as if statement statement.To be precise I want to do something like this,if(temp>0) so increment 'i' else do nothing.
temp?i++:WHAT_SHOULD_COME_HERE_SO_NO_CHANGES_ARE_MADE_ANYWHERE
Answer
Strictly speaking, you can't do this:
(boolean expression) ? (returning expression) : /* no-op */;
Something has to go in the third operand. However, you can make that "something" behaviorally equivalent to a no-op in terms of the post-conditions of evaluating the ternary operator. See below.
Explanation
The ternary operator must return a value, and the type is deduced as the most derived type that is a supertype of the return type of each of the second and third operands. So if the third operand is a blank expression (i.e. it returns nothing), then the compiler cannot deduce a return type for the operator as a whole. Thus, it will not compile.
Solution
Using the ternary operator:
If you really wanted to, this is how you might do it using the ternary operator:
i = temp>0 ? i+1 : i;
or
temp>0 ? ++i : i;
Preferred syntax:
Although if all you're looking for is a one-liner, then the following syntax is preferred:
if (temp>0) ++i;
This will work:
(void) ((temp>0)?i++:0);
Note that the (void) does not change the behavior of the code; rather it is there to indicate to the reader (and/or any style checking programs you might invoke in the future) that the result of the expression is being deliberately discarded. Without it you may get warnings from the compiler and/or other programmers suspecting a bug and trying to "fix" your code.
Actually, you may get that anyway, since the above is a very unusual way to express what you are trying to do. The code will be easier for others to understand and maintain if you instead use the traditional form:
if (temp>0) i++;
The ternary operator is used in an expression. As such, the entire expression must evaluate to a single value. This means that you must supply both the "if" and "else" clauses. There is no way to leave the "else" part blank.
In addition, embedding an increment operator within an expression such as this is inadvisable since the consequences of the side-effect are so error-prone.
you can:
int temp = 20, i = 0;
(temp)? i++: i;
cout << i << endl;
This question already has answers here:
Overloading ++ for both pre and post increment
(4 answers)
Closed 9 years ago.
I have these code of lines from a program my teacher made :
TimeKeeper& operator++() {
d_seconds++;
return *this;
}
const TimeKeeper operator++(int) {
TimeKeeper tk(*this);
++(*this);
return tk;
}
And one of the questions my teacher asked us was "operator++() returns a reference and operator++ (int) returns a value, explain why?"
Can anyone explain this to me??
If you need the rest of the code i dont mind putting it on!
Thanks!!
The one without an extra int is the preincrement operator while the one with the extra int parameter is the post increment operator. This somewhat awkward notation is somewhat of a hack to distinguish the two notations and the int can't be used for any useful purpose:
TimeKeeper keeper;
++keeper; // pre increment: calls TimeKeeper::operator++()
keeper++; // post increment: calls TimeKeeper::operator++(int)
The difference between pre increment and post increment is that for pre increment the value of the expression is that after the increment while for post increment it is the value before the expression. For post increment the object the increment is applied to gets moved forward and a different object representing the state before the increment is returned. The object representing the previous state is a temporary object which only lives within the expression and which, thus, needs to be returned by value. For the pre increment only one value is involved and that can be returned immediately by reference.
In the above snippet the result from keeper++ isn't used: you should only ever use the post increment operator when using its result. Otherwise it will just waste creating a temporary object pretty much along the lines of your teacher's code which is then thrown away. Even if the construction is cheap, it may waste a couple of CPU cycles. The same overloading and reasoning for not using it unless necessary applies to the decrement operator operator--(). Oddly enough, C++ is thus not idiomatic C++!
operator++() is the preincrement operator (++x), while operator++(int) is the post increment operator (x++). If you understand how these operations work, then you should be able to explain why one of them must return a copy.
Take a simple example:
int x = 1;
std::cout << x++ << "\n"; // prints 1
std::cout << ++x << "\n"; // prints 3
What happened to 2?
The value of x became 2 in the x++ expression, 1 was printed (the value of x prior to the increment operation).
In the second statement, the value of x becomes 3 in the ++x expression.
To distinguish these two operators there must be some syntaxical difference. So to distinguish postincrement operator from preincrement operator a parameter of type int that is not used was added to declaration of postincrement operator.
The preincrement operator returns the object itself. It is why its return type a refernce. The postincrement operator returns a temporary object and increment the original object. it is way it returns a value.
Can I use:
MyClass& MyClass::operator++ () {
a++; // private var of MyClass
return (*this);
}
Or it can be:
MyClass MyClass::operator++ ();
What's the difference?
Thanks for answers. I have another issue.
Many people do something like that:
MyClass& MyClass::operator++();
MyClass MyClass::operator++(int);
Isn't it illogical? Please give some examples if you can.
I know that the first version is pre-increment and the second is post-increment, but i ask why the first one returns reference but the second one not? It is in the same code (class), and the same use of the code.
No, you don't have to return the reference to your object when you overload the pre-increment operator. In fact you may return anything you'd like, MyClass, int, void, whatever.
This is a design issue -- you must ask yourself what is the most useful thing to the users of your class that you are able to return.
As a general rule, class operators are the most useful when they cause the least confusion, that is, when they operate the most like operators on basic types. In this case, the pre-increment operator on a basic type:
int i = 7;
j = ++i;
increments the variable and then returns the new value. If this is the only use you want MyClass to have, then returning a copy of your class is sufficient.
But, the pre-increment operator on a basic type actually returns an lvalue. So, this is legal:
int i = 7;
int *p = &++i;
If you want to support an operation like this, you must return a reference.
Is there a specific reason that you don't want to return a reference? Is that not a well-formed concept for your particular class? If so, consider returning void. In that case, this expression: ++myObject is legal, while this myOtherObject = ++myObject is not.
You can return whatever you want. void, reference to self, copy of self, something else. Whichever you prefer (or need).
If you plan using the ++ operator in chained expressions (like (++obj).something()) then return a reference. In you don't, then void is just fine.
Remember that in the end, operators are just like normal methods: you can do whatever you want with them, provided you respect their prototype.
For question two:
Prefix returns a reference, as expected.
Postfix returns a copy to be consistent with the behavior of the postfix operator(s).
Break it down simply to int:
int c = 0;
if(++c)
{
// true, prefix increments prior to the test
}
c = 0;
if(c++)
{
// false, c now == 1, but was incremented after the test
}
Implementing this behavior in a class requires a copy be returned because the postfix operator will have modified the state of the object.
If the program does not need true postfix operation, you are free of course to implement how you wish. While there are standard ways of writing these operators (that are understood by most C++ programmers), there's nothing actually stopping you from implementing this in different ways.
The argument provided about incorrect functionality surrounding (obj++)++ is not really important, as that code won't even compile for POD types (in Visual Studio 2010, at least), because for POD types, a copy is returned and that temporary copy cannot be used alone as an l-value.
However, for the prefix operator a reference is the preferred return as that allows the proper behavior for chaining the operation (++(++obj)).
Its not compulsory, but we should try to make operator overloading intuitive and it should work as per the operator which is being overloaded.
If we do
int i = 10;
i++ = 0
Then second statement is not allowed it says it requires lvalue as i++ denotes older state of i not a storage ...
while ++i = 0 perfectly works fine ..
so just to keep it in sync with actual operators prefix version had to return refence so that its return value may be treated as lvalue in expressions.
Yes, you should return by reference. No need for the parenthesis around *this.
EDIT: Replying to your comment... You don't have to return by reference. But in general we follow some guidelines which make our classes behave "as expected" when compared to the builtin semantics of such operators. You might wanna take a look at http://www.parashift.com/c++-faq-lite/operator-overloading.html.
I'm wanting to make sure I understand pass-by-value vs pass-by-reference properly. In particular, I'm looking at the prefix/postfix versions of the increment ++ operator for an object.
Let's suppose we have the following class X:
class X{
private:
int i;
public:
X(){i=0;}
X& operator ++ (){ ++i; return *this; } //prefix increment
X operator ++ (int unused){ //postfix increment
X ret(*this);
i++;
return ret;
}
operator int(){ return i; } //int cast
};
First of all, have I implemented the prefix/postfix increment operators properly?
Second, how memory-efficient is the postfix operator, compared to the prefix operator? Specifically how many X object copies are created when each version of the operator is used?
An explanation of exactly what happens with return-by-reference vs return-by-value might help me understand.
Edit: For example, with the following code...
X a;
X b=a++;
...are a and b now aliases?
It is more idiomatic to call the prefix increment of the object itself in the postfix increment:
X operator++(int)
{
X copy(*this);
++*this; // call the prefix increment
return copy;
}
The logic of incrementing an X object is thus solely contained inside the prefix version.
This is a correct implementation. It is typical that a postfix operator will be worse on performance because you have to create another copy before doing the increment (and this is why I've gotten in the habit of always using prefix unless I need something else).
With return-by-reference, you're returning an l-value reference to the current object. The compiler would typically implement this by returning the address of the current object. This means that returning the object is as simple as returning a number.
However, with return-by-value, a copy must be done. This means there's more information to copy over during the return (instead of just an address) as well as a copy constructor to call. This is where your performance hit comes in.
The efficiency of your implementation looks on-par with typical implementations.
EDIT:
With regards to your addendum, no, they are not aliases. You have created two separate objects. When you return by value (and when you created a new object from within the postfix increment operator) this new object is placed in a distinct memory location.
However, in the following code, a and b are aliases:
int a = 0;
int& b = ++a;
b is an address which references a.
Your operators are implemented correctly.
In the prefix operator, no copies of X are made.
In the postfix operator, one copy is made for ret, and potentially another copy is made when returning from the function, but all compilers will elide this copy.