The output is actually undefined. It can be either 11 or 22, but not 12. I'll explain them both.
You're getting 22 because
b = a
calls the copy constructor
A(A &a)
. This allocates a new val and then executes
*val = a.get();
a.get() increments *a.val to 1 and returns 1 (note that it's a pre-increment operator. Could that be the source of confusion?). Then *val = a.get() assigns 1 to *val.
So when you're done with line 13, a and b are both 1. Then line 14 calls the get() method on each one, which increment the value to 2 and return 2.
So why can it be 11 also? Because
b = a;
can be implemented in two ways and the compiler is free to pick either one. It can call the copy constructor (which it's doing here) or it call the default constructor followed by the assignment operator. In other words, it can do it like this:
If it did it like this then get() would not be called and both both *a.val and *b.val would contain 0 at the end of line 13. Line 14 would then increment both values to 1 and output 11.
This is why you should always define a default constructor and assignment operator if you define a copy constructor, and vice versa.
One more note: you should define a destructor that deletes val to avoid a memory leak.