The output of this piece of code is

21

I am unable to explain it to myself. My thinking (what I learned) is that an implicit copy constructor is called (triggered by the assignment) and all elements are copied bit by bit. However this does not apply to external elements, like the private variable val, which is a pointer. So b has a different pointer, but it is pointing to the same element.

So I expected the result to be

22

That is .get() is called twice by a and b and thus the dereferenced pointer value should be 1 (after the first get()) and then 2 (after the second get()). Finally the values are written to the console output.

C++ code:

#include <iostream>
using namespace std;

class A {
    int *val;
public:

    A() {
        val = new int;
        *val = 0;
    }

    int get() {
        return ++(*val);
    }
};

int main() {
    A a, b = a;
    cout << a.get() << b.get();
    return 0;
}
4

There are 4 answers

0
aslg On BEST ANSWER

This is what the code actually does:

cout.operator<<( a.get() ).operator<<( b.get() );

or

operator<<( operator<<( cout, a.get() ), b.get() );

(I can't get the latter to compile due to overloading issues, but it does happen behind the scenes)

Which means that the code evaluates std::endl before b.get(), and b.get() before a.get(). So b.get() increases val's pointed value by 1 and then returns 1, and a.get() increases val's pointed value by 1 and returns 2. The operators are called in the expected order after the parameters are evaluated. I'd guess this is compiler dependent, but I ran your code and got the 21 as well.

In this case you are using an implicit copy constructor. What it does is copy the memory of your instance a to instance b. (As you said, byte by byte)

So b now owns its own pointer which holds the same value as a's pointer, that is to the same address. Since you increase the value on get(), the returned value would never be the same so you would never get 22 as a result.

Edit: You didn't actually use std::endl, it's my habit.

4
Noel On

When using cout, evaluation of a.get() and b.get() is done in no specific order. Thus, in your example b.get() is evaluated first (to 1), and then a.get() (to 2), and then "21" is printed on screen.

0
BeyelerStudios On

Your problem is one of sequence points: std::cout << a.get() << b.get(); has no strict defined evaluation order for a.get() and b.get().

See this answer here for all the explanations.

0
Rndp13 On

First the get function is called for object b and then it is call for the object a, hence giving a o/p of 2 1

(gdb) s
main () at so2.c++:20
20          cout << a.get() << b.get();
(gdb) p &a
$6 = (A *) **0x7fffffffd0f0**
(gdb) p &b
$7 = (A *) *0x7fffffffd0e0*
(gdb) s
A::get (this=*0x7fffffffd0e0*) at so2.c++:14
14              return ++(*val);
(gdb) p *val
$8 = 0
(gdb) n
15          }
(gdb) p *val
$9 = 1
(gdb) s
A::get (**this=0x7fffffffd0f0**) at so2.c++:14
14              return ++(*val);
(gdb) s
15          }
(gdb) p *val
$10 = 2

From the above debuggging session we can see the flow and behavior.