The vec v1
itself consists of a triple pointer+len+capacity on the stack and data behind that pointer on the heap. A move of v1
to v2
will usually copy the stuff that's on the stack into the new variable, i.e. v2
is a different place on the stack that's also big enough to hold the (pointer, length, capacity) triple and the move will copy this triple from one place to the other.
The "move" part of moving then is achieved by the fact that the compiler knows and remembers that v1 cannot be used anymore after the move (unless it's a mutable variable, then you can move a new vector into it which will overwrite the invalidated triple that points to the same vec that's logically owned by v2
). You can think of the data in v1
after the move like garbage data, as if the variable is uninitialized again.
After v1
is moved out of, there will also not be any destructor calls on its old value when it goes out of scope or when it's assigned a new value. In tricky situations where it isn't statically known anymore whether at a particular place in the program v1 has been moved out of, the compiler will insert some extra "drop flag" boolean value on the stack that indicates whether v1
still contains a value that may be accessed and has to be dropped or whether all it contains is "garbage" that must not be accessed through v1
anymore. In such a situation the move itself will also result in this flag being updated.
Finally, and crucially, all this can change after compiler optimizations. The compiler may very well decide to make v1
and v2
actually use the same place on the stack, or even just the same registers without any stack usage, as long as such a change does not affect the program behavior. And in this case the move becomes a no-OP. Avoiding moves like that is in particular common for arguments and return values of a function, in case the function call gets inlined.
So in your code example, since v1
and v2
are never containing a (not moved out) value at the same time, I would be fairly confident that the compiler is turning the two variables into a single one and removing that move operation so that it does nothing at runtime. (In a release build only, where optimizations are turned on.)