[0][1][2]1std::vector<int> a{1, 2, 3};2auto b = a;3b[0] = 9;4auto c = std::move(a);5std::cout << a.size();[0]1[1]2[2]3ptrsizeptr→#1size3ptrsize123→#1
Violet card: the code; a line glows while it runsKhaki blocks: the vector objects (pointer + size); slate blocks: heap memoryInk arcs: pointers. Tokens: values copied one by one, or one pointer handed overOn the left: five lines of C++. On the right: heap block #1 at the back, the vector objects a, b and c in the middle (a pointer and a size each), heap block #2 in front; the ink arcs are the pointers. Copying a into b makes a new block and copies each element into it. Moving a into c hands block #1 over: one pointer moves, no element is copied, and a is left empty. At the closing brace c, b and a are destroyed in reverse order, and each block is freed exactly once. 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.

Copying

  1. 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.

Moving

Cleaning up

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.