It's well defined safe to use a vector after a move:
Move constructor. Constructs the container with the contents of other using move semantics. Allocator is obtained by move-construction from the allocator belonging to other. After the move, other is guaranteed to be empty().
What he probably means is he imagines the moved-from vector still has elements in it, and indexes into the empty. Another argument for at() outside loops.
Yes, and most algorithms are "surpising" when a container is empty. Most people write, then read, algorithm code imagining a container full of elements. I've been caught by that "bug" so many times, that I now annotate (Java) when containers can be empty. The first few times co-workers see it, they are confused. They they re-read the code, and "oh, I get it. when empty, the code path is very different!" Unlike nullable values, empty collections (usually) don't cause exceptions.
Which can be a useful property at times, but also means tooling won't help you here since it's not an obvious bug.