T_Igor
T_Igor

Reputation: 53

Can't explain compiler's behavior

Consider this simple code:

class A {
public:
    int value;
    A(int value) { this->value = value; }
    ~A() { printf("destroying %d\n", value); }
    A operator ++() { return A(value + 1); }
};

int main() {
    A a(1);
    printf("before increment: %d\n", a.value);
    a = ++a;
    printf("after increment: %d\n", a.value);
    return 0;
}

This outputs:

before increment: 1
destroying 2
after increment: 2
destroying 2

Why is the value of a 1 more before being destroyed?

Upvotes: 4

Views: 160

Answers (3)

LookAheadAtYourTypes
LookAheadAtYourTypes

Reputation: 1689

In operator++ method you create temporary A object which is then destroyed when you return it from the function. There should be also another copy construction and destroying, but RVO elides this one.

When you add log to constructor also you will see better what is going on. I also allowed myself to change printf to cout, for more c++ish coding style.

#include <iostream>

class A {
public:
    int value;
    A(int value) {
        std::cout << "creating " << value << std::endl; 
        this->value = value; 
    }
    ~A() { 
        std::cout << "destroying " << value << std::endl; 
    }
    A operator ++() { return A(value + 1); }
};

int main() {
    A a(1);
    std::cout << "before increment: " << a.value << std::endl; 
    a = ++a;
    std::cout << "after increment: " << a.value << std::endl; 

    return 0;
}

output:

creating 1
before increment: 1
creating 2
destroying 2
after increment: 2
destroying 2

You can also read about canonical implementations of operators overloading:

http://en.cppreference.com/w/cpp/language/operators

operator++ overloading should look like this:

struct X
{
    X& operator++() // prefix version
    {
        // actual increment takes place here
        return *this;
    }
    X operator++(int) // postfix version
    {
        X tmp(*this); // copy
        operator++(); // pre-increment
        return tmp;   // return old value
    }
};

Upvotes: 4

Teivaz
Teivaz

Reputation: 5665

int main() {
    A a(1); // a.value = 1;
    printf("before increment: %d\n", a.value);
    a = ++a; // 1. create temporary object of type A with a.value+1
             // 2. copy temporary object to object a.
             // 3. destroy temporary object.
    printf("after increment: %d\n", a.value);
    return 0;
}

Basically you can declare pre-increment operator here as constant for clarity

A operator ++() const { return A(value + 1); }

But expected behavior is:

A& operator ++() { ++value; return *this; }

Upvotes: 2

Hatted Rooster
Hatted Rooster

Reputation: 36463

It's pretty simple:

a = ++a;

First, a new temporary A object is created that holds a value of 2 (value + 1 = 2), this object is moved/copied to a and then destroyed (which is the first destroying 2 print you see). Now the compiler generated move/copy constructor just does a memcopy of the members, value in this case. value was 2 when assigned to the temp object and thus a's value will be 2 too. Therefore, the final two printf's printing out 2 is nothing surprising.

Upvotes: 0

Related Questions