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.
Related
This question already has answers here:
Difference between pre-increment and post-increment in a loop?
(22 answers)
Closed 2 years ago.
I was having a discussion with a stubborn person I know over which of these two forms was more semantically correct, although there is no logical difference to the code:
1.
for(int x = 0; x < 10; x++)
// do something
2.
for(int x = 0; x < 10; ++x)
// do something
Is it better to pre-increment or post-increment in a for loop?
If you don't need the side effect of post increment, then the pre increment version is the better choice.
In case of an int it does not result in different code, but in case of an iterator you probably get better performance with pre increment because post increment needs to create a temporary copy of the original iterator. You can easily see that when comparing pre increment
class T {
T& operator++() {
this-> .... // do the increment
return *this;
}
}
with the post increment
class T {
T operator++(int) {
const T old{ *this };
this-> .... // do the increment
return old;
}
}
If the iterator is just a pointer then the compiler might be able to optimize so much that you don't see a difference, but if the iterator is more complex, then you will see a difference.
Of course the same applies to prefix and postfix decrement.
If a modern compiler with optimisations switched on produces different code for x++ and ++x for this particular case then you ought to switch compiler vendors.
I always write ++x since (i) the type of x might change to a non-POD in the future and x++ could take an expensive copy in such a case, (ii) because it buries a message in your code that you think about things like this, and (iii) because I'm old fashioned.
(I insist on ++x in my company.)
Does not matter.
Might matter for iterators instead of ints, but actually does not matter to them either.
I'd yield to a stubborn person.
Or retreat by saying "i += 1" (but that may be worse for iterators)
// pre-fix operator
MyCustomClass& operator++()
{
return *this;
}
// post-fix operator
MyCustomClass operator++(int)
{
MyCustomClass tmp(*this);
operator++();
return tmp;
}
and as a best practice:
to be consistent with the built in operators, your built in postfix operator
should return the old value, thar value is returned as a value and never as a reference
but for prefix operators you should return a reference to the modified object.
This question already has answers here:
Is there a performance difference between i++ and ++i in C++?
(20 answers)
Closed 6 years ago.
I usually think that preincrement is more efficient than postincrement in C++. But when I read the book Game Engine Architecture(2nd ed.) recently, there is a section says that postincrement is prefered than preincrement in for loop. Because, as I quote, "preincrement introduces a data dependency into your code -- the CPU must wait for the increment operation to be completed before its value can be used in the expression." Is this true? (It is really subverted my idea about this problem.)
Here is the quote from the section in case you are interested:
5.3.2.1 Preincrement versus Postincrement
Notice in the above example that we are using C++’s postincrement operator,
p++, rather than the preincrement operator, ++p. This is a subtle but sometimes important optimization. The preincrement operator increments the contents of the variable before its (now modified) value is used in the expression. The postincrement operator increments the contents of the variable after it has been used. This means that writing ++p introduces a data dependency into your code -- the CPU must wait for the increment operation to be completed before its value can be used in the expression. On a deeply pipelined CPU, this introduces a stall. On the other hand, with p++ there is no data dependency. The value of the variable can be used immediately, and the increment operation can happen later or in parallel with its use. Either way, no stall is introduced into the pipeline.
Of course, within the “update” expression of a for loop (for(init_expr;
test_expr; update_expr) { ... }), there should be no difference between
pre- and postincrement. This is because any good compiler will recognize that
the value of the variable isn’t used in update_expr. But in cases where the
value is used, postincrement is superior because it doesn’t introduce a stall
in the CPU’s pipeline. Therefore, it’s good to get in the habit of always using
postincrement, unless you absolutely need the semantics of preincrement.
Edit: Add "the above example".
void processArray(int container[], int numElements)
{
int* pBegin = &container[0];
int* pEnd = &container[numElements];
for (int* p = pBegin; p != pEnd; p++)
{
int element = *p;
// process element...
}
}
void processList(std::list<int>& container)
{
std::list<int>::iterator pBegin = container.begin();
std::list<int>::iterator pEnd = container.end();
std::list<inf>::iterator p;
for (p = pBegin; p != pEnd; p++)
{
int element = *p;
// process element...
}
}
pre-increment introduces a data dependency into your code -- the CPU must wait for the increment operation to be completed before its value can be used in the expression."
Is this true?
It is mostly true - although perhaps overly strict. Pre increment doesn't necessarily introduce a data dependency - but it can.
A trivial example for exposition:
a = b++ * 2;
Here, the increment can be executed in parallel with the multiplication. The operands of both the increment and the multiplication are immediately available and do not depend on the result of either operation.
Another example:
a = ++b * 2;
Here, the multiplication must be executed after the increment, because one of the operands of the multiplication depends on the result of the increment.
Of course, these statements do slightly different things, so the compiler might not always be able to transform the program from one form to the other while keeping the semantics the same - which is why using the post-increment might make a slight difference in performance.
A practical example, using a loop:
for(int i= 0; arr[i++];)
count++;
for(int i=-1; arr[++i];) // more typically: (int i=0; arr[i]; ++i;)
count++;
One might think that the latter is necessarily faster if they reason that "post-increment makes a copy" - which would have been very true in the case of non-fundamental types. However, due to the data dependency (and because int is a fundamental type with no overload function for increment operators), the former can theoretically be more efficient. Whether it actually is depends on the CPU architecture, and the ability of the optimizer.
For what it's worth - in a trivial program, on x86 arch, using g++ compiler with optimization enabled, the above loops had identical assembly output, so they are perfectly equivalent in that case.
Rules of thumb:
If the counter is a fundamental type and the result of increment is not used, then it makes no difference whether you use post/pre-increment.
If the counter is not a fundamental type and the result of the increment is not used and optimizations are disabled, then pre-increment may be more efficient. With optimizations enabled, there is usually no difference.
If the counter is a fundamental type and the result of increment is used, then post-increment can theoretically be marginally more efficient - in some CPU architecture - in some context - using some compiler.
If the counter is not a fundamental type and the result of the increment is used, then pre-increment is typically faster than post-increment. Also, see R Sahu's answer regarding this case.
One point of data from my experience.
Changing a post-increment to a pre-increment of a std::map::iterator in for loops resulted in noticeable savings in a core algorithm at my work.
In general, when icrementing an iterator that is a class, i.e. it is not a pointer, you should notice savings when using the pre-increment operator. The reason for it is that the pre-increment operator function changes the object in place while the post increment operator function usually involves creation of a temporary object.
A pre-increment operator is usually implemented as:
typename& typename::operator++()
{
// Change state
...
// Return the object
return *this;
}
while a post-increment operator is usually implemented as:
typename typename::operator++(int)
{
// Create a temporary object that is a copy of the current object.
typename temp(*this):
// Change state of the current object
...
// Return the temporary object.
return temp;
}
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.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am new in C++ and I've got some questions. I saw operator ++ overloading at complex numbers and I cant understand:
Why I create a tmp variable
why my first operator is Complex & and second it's just Complex
Why return *this;(i know cause of Complex& but why)
if i used Complex without & what would happened?(i run it and its the same result)
Don't look at comments it's Greek :)
Complex & Complex::operator ++(){
r=r+1;
return *this;//to this einai to pointer tou trexontos alla 8eloume dereference ara vazoume *this gia na epistrepsoume refernce//
}
Complex Complex::operator ++(int ){
Complex tmp(*this);
operator ++();
return tmp;//ftiaxnoume ena tmp tou antikimenou pou exoume meta efarmozoume to operator++ kai epistrefoume to tmp//
}
the different signature (Complex& vs Complex) is because these operations i++ and ++i do different things. One returns a copy of the old value (the second one) by value, the first one returns a reference to the actual value if x - by reference
The tmp variable is needed because you need to return the old value after incrementing the value (thats what x++ does)
you need to return a reference to the current object - so return *this - this is a pointer to the current object; *this is the object
2 - Complex & returns a reference to the same object, Complex returns a copy of it.
1 - that is why a temp variable is created, in order to increment the actual object but return the copy, in order to simulate the "use and then increment" postfix operator.
3 - because while i++ returns a copy of i (and increments i), ++i returns i incremented.
4 - the operator will return a copy of the incremented object, not the actual incremented object.
With a variable x, you can write ++x or x++. Former will do a ++, and if it is part of a bigger expression, use the new x. Latter will do the ++ too, but uses the old x for the current expression (it´s like the ++ comes a line after the current one).
If you overload ++, you need to separate if it is prefixed or suffixed.
It looks somewhat strange, but if you mean the suffixed version, you need to have a nameless int as parameter of the function (nothing for prefix). There is no meaningful value passed or something,
it´s just to make a difference between the two possibilites.
So, in the suffix variant, you´ll have a temporary copy to keep
the old value while you´re doing the ++ (ant return the old value for this one time).
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.