Postfix Increment/Decrement Operator

May 11, 2012 at 8:12pm
Hello,

I am currently learning about overloading the postfix increment and decrement operators. Currently, I am evaluating this code snippet from LearnCpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Digit Digit::operator++(int)
{
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);
 
    // Use prefix operator to increment this digit
    ++(*this);             // apply operator
 
    // return temporary result
    return cResult;       // return saved state
}
 
Digit Digit::operator--(int)
{
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);
 
    // Use prefix operator to increment this digit
    --(*this);             // apply operator
 
    // return temporary result
    return cResult;       // return saved state
}
 
int main()
{
    Digit cDigit(5);
    ++cDigit; // calls Digit::operator++();
    cDigit++; // calls Digit::operator++(int);
 
    return 0;
}


I am really curious about how the postfix operator works. I see that this code DOES work, but I just do not understand how. I understand that the postfix operator is supposed to evaluate the object, then increment. Could somebody bother to explain to me how the postfix operator differs from the prefix operator, and maybe specifically in this code?

Thanks,
Flurite
May 11, 2012 at 8:25pm
Your code is showing two postfix operators and no prefix operator.
May 11, 2012 at 8:30pm
Prefix for this code would be something like...

1
2
3
4
5
Digit Digit::operator++()
{
     ++m_nDigit;  //Notice no copy is made, which means the digit returned will be incremented.
     return *this;
}


The postifix, creates the copy, then increments the original, and then returns the copy. Which means the return value is not incremented, but the next expression that uses the variable (original) will have it's value incremented (just like the copy).

In other words.
1
2
3
4
5
6
7
8
9
10
//...
Digit original(1); //initialize digit to 1.
Digit copy = original++; 

//the member m_nDigit is 1, before entering the post fix operator
//(1) First a temp copy of *this is created, where m_nDigit == 1.
//(2) Second the original is incremented (so m_nDigit of "this" is incremented to two).
//(3) Third, the return, returns the temporary Digit variable, which was initialized with m_nDigit == 1 when we did step (1) in this operator.
//(4) Fourth The return value of the operator is copy constructed into Digit copy (which remember is still m_nDigit == 1)
//(5) Fifth, after the ; (line 4 of code) the variable "original" m_nDigit is now 2. 
May 11, 2012 at 8:31pm
With my bad English I will try to explain. The postfix operator returns current state of the object. For example,

1
2
int x = 10;
int y = x++;


y will have value equal to 10.

Thus in the code

1
2
3
4
5
6
7
8
9
10
11
Digit Digit::operator++(int)
{
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);
 
    // Use prefix operator to increment this digit
    ++(*this);             // apply operator
 
    // return temporary result
    return cResult;       // return saved state
}


the statements

Digit cResult(m_nDigit);
and

return cResult; // return saved state

provide that the current state of the object will be returned. And the statement

++(*this); // apply operator

does the increment affter the current state of the object is prepared to be returned.
May 11, 2012 at 8:38pm
@clanmjc,

Thanks, your explanation really helped. I'm just wondering why would the incremented result only show up till the next usage of the instance. Are you able to explain?

@vlad from moscow,

Cool! I see that the function returns an unchanged result, but I am still wondering why the object does not increment right when it's called, like the prefix operator form. After all, we increment the class in the function.

Thanks for the help so far!
May 11, 2012 at 9:08pm
I'm just wondering why would the incremented result only show up till the next usage of the instance. Are you able to explain?


Well, technically it's not, it has been incremented, what you are noticing is the return result. The return result is not the original object, it is the copied object.

Let me show you an incorrect implementation:

1
2
3
4
5
Digit operator++(){
   ++(*this); //increment this first... !!!! wrong in the post fix, should have copied first.
   Digit temp(m_nDigit); //Now we copied, but it's already been incremented.
   return temp; //we returned temp, which has the increment copied value.
}


Now if you did something like.
1
2
Digit original(1);
Digit value = original++; //value gets initialized with 2, because that is what is returned. 


Just by changing when the copy is made, changes the result you see from the returning of the operator call. This incorrect implementation is the exact implementation of the prefix (except that, there is no copy made because it is pointless, what is the copy doing, so we omit it in the prefix implementation like my previous post.)

May 11, 2012 at 9:09pm
It is the meaning of the word "postincrement". So firstly the current state of the object is returned and only after that the object is incremented. If for example to change the order of the statements in the function and to write

1
2
3
4
5
6
7
8
9
10
11
Digit Digit::operator++(int)
{
    // Use prefix operator to increment this digit
    ++(*this);             // apply operator
 
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);
 
    // return temporary result
    return cResult;       // return saved state
}


then we get the state of the object after the increment. So a question arises how to get the state of the object before its increment? So we use the copy constructor

1
2
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);


to make a copy of the current state of the object and after that increment the object itself.

1
2
    // Use prefix operator to increment this digit
    ++(*this);             // apply operator 


Now we are ready to return the state of the object before the increment

1
2
    // return temporary result
    return cResult;       // return saved state 
Last edited on May 11, 2012 at 9:11pm
May 11, 2012 at 9:49pm
@clanmjc and vlad from moscow,

Okay, I see how the value returns its original class first and makes a copy of the operand class (not a exact copy, but a copy of the value). So the return value become the result of the operand?

Even though the return operand becomes the value of the class increment, the class has the new incremented value, and must be seen in the next usage of the class.

Is this correct?
May 11, 2012 at 10:22pm
Pretty much, yeah.
May 11, 2012 at 10:45pm
So the return value become the result of the operand?


The return copy of the original object becomes the result of the operator function. While the object itself gets new state that is its state is changed.

As in the example

1
2
int x = 10;
int y = x++;


y gets the copy of the original object x while x itself is changed and its new state will be seen after that statement.

So there is a difference between declaration of the preincrement and postincrement operators.

The preincrement returns reference to the original object

Digit & Digit::operator ++();

while the postincrement operator returns a copy (usually const unnamed object) of the original object before the increment

Digit Digit::operator ++( int );
or

const Digit Digit::operator ++( int );
May 11, 2012 at 11:23pm
Thank you very much. I think I understand now!
Topic archived. No new replies allowed.