nakiya
nakiya

Reputation: 14413

Why does this code `misbehave`?

#include <iostream>
 using namespace std;

struct X
{
    int i_Val;

    X(int iVal)
        :i_Val(iVal)
    {
    }

    X& operator++()
    {
        cout << "X::operator++()" << endl;

        ++i_Val;
        return *this;
    }

    operator int() const
    {
        return i_Val;
    }
};

const X operator+(const X& lhs, const X& rhs)
{
    cout << "operator+(const X&, const X&)" << endl;
    return lhs.i_Val + rhs.i_Val;
}

int main()
{
    X x = 5;
    X y = (++x) + (++x) + (++x);

    cout << y << endl;
}

compile and run. It produces the output:

X::operator++()
X::operator++()
X::operator++()
operator+(const X&, const X&)
operator+(const X&, const X&)
24

But I expected this:

X::operator++()
X::operator++()
operator+(const X&, const X&)
X::operator++()
operator+(const X&, const X&)
22

Who's at blame? Me or the compiler?

Upvotes: 0

Views: 155

Answers (3)

Puppy
Puppy

Reputation: 146940

This is not undefined behaviour or a dupe of some i++ = ++i misery, because an overloaded operator is a function call and an implicit sequence point is introduced.

However, it's my understanding that the order of evaluation in this context is unspecified and the compiler is free to re-order this however it likes.

Upvotes: 4

Lee Louviere
Lee Louviere

Reputation: 5262

The produced output is more sound mathematically. Do everything in all parentheses once left to right, then do the parent operation.

Upvotes: 0

tgmath
tgmath

Reputation: 13541

DeadMG gave the right answer.

If you like to get a 22 you can try a different compiler. ;)

icc gives me your desired output and the gcc produces the 24.

Upvotes: 0

Related Questions