++ operator overloading - please explain

I'm overloading the ++ operator with the following code in a sample class I wrote. The code seems to work fine.

1
2
3
4
5
6
Flower Flower::operator++(int)
{
    Flower temp(*this);
    stemLen++;
    return temp;
}


The "function" (probably wrong term) returns an object of type Flower. The 1st line creates this new object. How come the second line works as is and not temp.stemLen++; ? It seems like it is modifying the local variable and not the one in the new object created one line before. The last row returns this new object and somehow it holds the correct data as I want. What goes on here?
Last edited on
What you have is a post-increment operator.

To post-increment an object means doing three things:
1) make a copy of the object, preserving the old value
2) increment the object
3) return the copy with the preserved old value

in your case, the line stemLen++ is incrementing the member variable of the object on which the operator was called.
operator++(int) is the postfix operator, which should return a copy of *this prior to performing the increment operation. If you do temp.stemLen++, your postfix operator will be such that x++ will be functionally equivalent to x+1. It will return *this incremented without incrementing *this.
So stemLen++ does actually promote the local variable of *this (which is the object that called the ++ operator to begin with?

If so, temp is created as a copy of *this before the promotion, so how come when it gets returned the variable is promoted? The local variable of temp is untouched as far as I can see and created before the promotion so it is an "old" copy.
"Promote" has a technical meaning. Please use "increment" instead.

how come when it gets returned the variable is promoted?
Do you mean that if you do
1
2
Flower x;
Flower y = x++;
y.stemLen does not equal x.stemLen - 1?
Lets say I'm doing:
1
2
 Flow f1("","",4);
 f1++;


So now stemLen = 5. The above is like writing f1 = f1++, so first thing an old copy is created (called temp) and the local variable in incremented and afterwards temp is being returned so that f1 points at temp, however how come temp holds the incremented value if I am increment the local variable in f1 which is overwritten in the assignment?

Perhaps this helps making my question a bit more clear? Obviously I'm missing out on something as the code works.
Last edited on
> The above is like writing f1 = f1++
I think that that is undefined behaviour.

> if I am increment the local variable in f1
¿what local variable?
1
2
3
4
5
6
Flower Flower::operator++(int)
{
    Flower temp(*this);
    this->stemLen++; //just for clarity
    return temp;
}
you increment the member variable `stemLen' of the object `f1'

> how come temp holds the incremented value
It doesn't, ¿how are you observing that?

> so that f1 points at temp
¿ah? `f1' is not a pointer
I think that that is undefined behaviour.
It ought to be defined for overloads, don't you think? Doesn't seem like there's much the compiler can do to mess with the order of evaluation.
Perhaps my terminology in incorrect...
f++ = f=f+1
I think we can agree that the above is true.

The 1st line of the function calls a copy constructor which creates a new object called temp. temp holds the same values as f, including the variable stemLen. On the 2nd line the local member (of f in this case) in incremented. As far as I can understand this does not alter the values stored in temp. On the third line temp is returned as reference. Who catches (wrong term?) this passed reference and who needs it if the value in it's member is not incremented?
Last edited on
Who catches (wrong term?) this passed reference
You can assign the return value to another Flower, like I did in my last example. If the value isn't assigned, the temporary is discarded. <edit>If the constructor and operator overload are inlineable, the compiler could conceivably decide not to create the temporary at all for that particular usage of the operator.</edit>

who needs it if the value in it's member is not incremented?
It's occasionally useful to in/decrement a value and keep the old value. This is evidenced by the fact that the postfix operators exist.
Last edited on
OK so in this specific case there is no real use for the temp object and the form of the overloading function is due to the language inherent structure?

Without overloading anything a function that does the same thing could look like so:
1
2
3
4
void Flower::incStemLen();
{
    this->stemLen++;
}
If you don't want to return the unmodified value, then just overload the prefix operator.
1
2
3
4
5
6
//You can also return a 'Flower' instead of a 'const Flower &', but this avoids a copy.
const Flower &Flower::operator++() //Note: no int
{
    this->stemLen++;
    return *this;
}
Who needs?

Well, most of the time you could write:
1
2
y = x;
++x;

But occasionally the ability to write it more compactly y = x++; is just neat.
See http://www.cplusplus.com/reference/algorithm/merge/

In case you did not read the GotW, a canonical post-increment is:
1
2
3
4
5
Flower Flower::operator++(int) {
    auto old = *this; // remember our original value
    ++*this;          // always implement postincr in terms of preincr
    return old;       // return our original value
}

That obviously depends on Flower copy constructor and
1
2
3
4
5
Flower& Flower::operator++()
{
    ++(this->stemLen);
    return *this;
}
Topic archived. No new replies allowed.