Here's the quick and simple: when you pass by value, a copy of "thing" is placed on the stack and used by the routine that is being called. If the called routine makes a change, it is changing the copy. The change will not be seen by the caller.
When passing by reference, a pointer to the "thing" is passed to the called routine. If the called routine makes a change, it is changing the actual value and will be visible to the caller.
-Mike