Alex24
Alex24

Reputation: 610

How post-increment operator works with user defined types?

I have a difficulty on how this post-increment operator works for user-defined types: As I guess the Post-Increment operator operator++(T _unused) saves the original value first (into the expression) then increment the variable. e.g:

int x{5};
int y{x++};

So x = 6 and y = 5 and that's ok.

But here is an example of user-defined:

struct s{
    int x;
    s(int m_) : x(m_){}
    s operator++(int){ x++; return *this;}
};


int main(){

    s a(0);
    a.x = 7;
    cout << "a::x: " << a.x << endl;

    s b(a++);

    cout << "a::x: " << a.x << endl; // 8
    cout << "b::x: " << b.x << endl; // 8 ?!

    int t = 9;
    s c(t++);

    cout << "c::x: " << c.x << endl; // 9
    cout << "t: " << t << endl; // 10 ok

    cout << endl;
    return 0;
}

As you can see above: s b(a++) will make the values of a.x and b.x 8? I can't understand why?

Thank you guys for your help and time and efforts.

Upvotes: 1

Views: 220

Answers (5)

Raindrop7
Raindrop7

Reputation: 3911

What should you expect from: s operator++(int){ x++; return *this;}?

You can see that x is incremented before the copy constructor constructs the temporary object. Remember returning by value invokes copy constructor. You should construct the temporary object before incrementing the variable.

In your case you can change it to look like:

s operator++(int){ 
    return s(x++);
}

AS you can see above the temporary object is constructed with x's value then x is incremented.

Upvotes: 0

Jans
Jans

Reputation: 11250

Change the operator to this:

s operator++(int){ 
   s t{x++};
   return t;
}

The problem is that you're defining the operator in a way that it modify this before returning and the return is a copy of this modified, what you need is create a new s with the value of x before modification and return that instead.

Upvotes: 3

Jarod42
Jarod42

Reputation: 218088

How post-increment operator works with user defined types?

The way you write it, as it is mostly a regular method.

It is good practice to avoid surprise, and so mimic behaviour of built-in types is good.

To mimic built-in type as int, you might fix implementation to:

struct s
{
    int x;
    explicit s(int m_) : x(m_){}
    s& operator++(){ ++x; return *this;} // pre-increment
    s operator++(int){ auto res = *this; ++*this; return res;} // post-increment
};

Upvotes: 3

Pete Becker
Pete Becker

Reputation: 76438

You typically provide two overloads for the increment operator in a class:

class C {
public:
    C& operator++();   // pre-increment
    C operator++(int); // post-increment
    int i;
};

The thing is, naming these "pre-increment" and "post-increment" describes how they're called, not what they do.

C c;
++c; // calls operator++()
c++; // calls operator++(int)

To implement the usual semantics of pre- and post-increment you have to write code that does the appropriate thing.

Pre-increment means incrementing the value, and returning the new value:

C& C::operator++() {
    ++i;
    return *this;
}

Post-increment means incrementing the value and returning the old value:

C C::operator++(int) {
    C res(*this);
    ++*this;
    return res;
}

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385295

You don't get a post-increment just by adding int to the function signature: you have to actually implement it!

Your code:

s operator++(int){ x++; return *this;}

This looks just like a pre-increment to me. Although it'll be called when you write someSObject++, all it does is increment the object's own x then return a copy of the object.

Instead, I think you meant something like:

s operator++(int)
{
    S result{*this};
    ++(*this);
    return result;
}

Or, tailored to this specific class for brevity:

s operator++(int)
{
    return s{x++};
}

Upvotes: 2

Related Questions