'How does object initialization ambiguity get resolved?

The class has two constructors, one that has no initialization value and does not increase the 'val', the other takes a reference to an object, and increases 'val'. How come, by initializing with 'A a,b = a;' a.get << b.get outputs '22' ? I expected '12'. Many thanks in advance.

class A
{
    int *val;
public:
    A() { val = new int; *val = 0;  }
    A(A &a) { val = new int; *val = a.get(); }
    int get() { return ++(*val); }
    ~A () { delete val; }
};


main:
[...]
   
    A a,b = a;
    cout << a.get() << b.get(); // 22 ????
    //cout << a.get(); // 1 if A a init, 2 if A a = a init, OK.
    //cout << a.get() << b.get(); // 33 if A a = a, A b = a init.
                                
[...]


Solution 1:[1]

Because in the A copy-constructor (which should really take its arguments as a reference to a const) you call a.get(). That increases *a.val from 0 to 1.

Then you call a.get() for the output, which increases *a.val from 1 to 2.

To get the expected behavior you should copy *a.val directly instead:

A(A const& a)
    : val(new int(*a.val))
{}

Solution 2:[2]

a is default-constructed, so it sets *(a.val) to 0.

b is copy-constructed from a, so it first calls a.get(), incrementing *(a.val) to 1 and returning that new value, so *(b.val) gets set to 1, not 0.

Then you print the output of calling a.get() and b.get(), incrementing both *(a.val) and *(b.val) to 2 and returning those new values.

That is why you see 22 displayed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Some programmer dude
Solution 2