in reply to When does $_ get used?

You're confusing $_ with the return from shift. shift will assume @_ if it isn't given an argument, but it will not assign its return value to $_. None of the functions will ever assign their return value to @_ or $_. If there is no-one to receive the value, the return value is discarded.

Now, the reason that foreach(@array) works the way you think it does is because that's a property of foreach. while does not have this property. That may have been the piece of info you were missing.