In C bitwise left shift operation invokes Undefined Behaviour when the
left side operand has negative value.
[...]
But in C++ the behaviour is well defined.
[...] why [...]
The easy answer is: Becuase the standards say so.
A longer answer is: It has probably something to do with the fact that C and C++ both allow other representations for negative numbers besides 2's complement. Giving fewer guarantees on what's going to happen makes it possible to use the languages on other hardware including obscure and/or old machines.
For some reason, the C++ standardization committee felt like adding a little guarantee about how the bit representation changes. But since negative numbers still may be represented via 1's complement or sign+magnitude the resulting value possibilities still vary.
Assuming 16 bit ints, we'll have
-1 = 1111111111111111 // 2's complement
-1 = 1111111111111110 // 1's complement
-1 = 1000000000000001 // sign+magnitude
Shifted to the left by 3, we'll get
-8 = 1111111111111000 // 2's complement
-15 = 1111111111110000 // 1's complement
8 = 0000000000001000 // sign+magnitude
What forced the ISO C++ committee to consider that behaviour well
defined as opposed to the behaviour in C?
I guess they made this guarantee so that you can use << appropriately when you know what you're doing (ie when you're sure your machine uses 2's complement).
On the other hand the behaviour is implementation defined for bitwise
right shift operation when the left operand is negative, right?
I'd have to check the standard. But you may be right. A right shift without sign extension on a 2's complement machine isn't particularly useful. So, the current state is definitely better than requiring vacated bits to be zero-filled because it leaves room for machines that do a sign extensions -- even though it is not guaranteed.