Shifting a negative signed integer to the right may or may not propagate the sign bit, the results of right shifting a negative are implementation defined in C++.Shifting a signed integer to the right propagates the sign bit, which results in the correct result.
... and that, by the way, encroaches on the dark corners of C++ that you best avoid.
Worse yet is undefined-behavior, in which the compiler might do with values it knows at compile-time is sometimes different than what the CPU would do if left to its own devices with run-time values. For example, If you shift a 32bit unsigned value of 1 left 32 positions under VS2012 for x86 target, and both the '1' and the shift amount are known, the compiler's optimizer folds this away and the apparant result is 0. However, if one of them is a runtime value, the operation must be executed by the CPU, and on x86 (and x64, it happens) the result is 1.
To plug an article I wrote for the Visual C++ team blog that talks about this kind of thing from a perspective of undefined/implementation-defined behaviors that might bite you when moving from x86/x64 to ARM, see Hello ARM: Exploring Undefined, Unspecified, and Implementation-defined Behavior in C++.
Plenty can go wrong when programmers play fast and loose with the standard, and end up being too clever by half
[Edit] Slight pivot to be more precise, as SiCrane pointed out below.