Copying
Line 1 makes a vector a. The object a itself is small: a pointer and a size. Its three numbers live in a separate block on the heap (memory requested while the program runs), and a owns that block.
auto b = a; makes b as a copy of a. The copy constructor asks for a new heap block and copies every element into it. Now b points to its own block #2 with the same values. This is a deep copy.
b[0] = 9; changes only b's block. a still holds 1, 2, 3. That is the point of a copy: two objects with separate memory, so changing one never changes the other.
A copy does work in proportion to the size: one new block plus one copy per element. Three ints are cheap. A vector of a million ints means a million copies, even if you never use the original again.
Moving
std::move(a) moves nothing by itself. It is a cast: it turns a into an rvalue reference (written T&&), a note that says 'you may take my resources'. That note picks the move constructor instead of the copy constructor.
auto c = std::move(a); runs the move constructor. c takes a's pointer and size, and a's pointer is set to null. No new block and no element copied: block #1 just changes owner. Constant time, whatever the size.
a still exists, but it is empty: a.size() prints 0. A vector is guaranteed empty after a move; most other standard types are only 'valid but unspecified'. Safe things to do with a: give it a new value, or let it be destroyed.
Cleaning up
At the closing brace the destructors run in reverse order: c frees block #1, b frees block #2, and a has nothing to free. Because a let go of its pointer, block #1 is freed exactly once, never twice.
A class that owns a resource needs five special members: destructor, copy constructor, copy assignment, move constructor and move assignment. Simpler: build classes from members like std::vector, which already get these right. That is the rule of zero.
What happens
;; step 1/9 · own
1 std::vector<int> a{1, 2, 3};
a ptr → block #1, size 3 (small, fixed size)
block #1 [1, 2, 3] (on the heap)
owns = a must free block #1 when a is destroyed
The figure draws a vector as a pointer and a size. Real libraries (libstdc++, libc++, Microsoft's STL) keep three pointers: the start of the elements, their end, and the end of the reserved space. The idea is the same. cppreference lists std::vector's copy constructor as linear in the size of the other vector and its move constructor as constant.