C++ PROGRAMMING ยท 15 MIN STUDY

Dynamic sequences with std::vector

Use std::vector for a resizable sequence, safe indexing, iteration, and common operations.

Learning objectives

  • Explain why a vector is useful when the number of elements can change.
  • Create, append, inspect, and iterate through a vector.
  • Distinguish size from capacity.
  • Recognize index and iterator invalidation risks.

Prerequisites: understand variables, arrays, zero-based indexing, and loops. Review Variables, Arrays, and Loops first.

Array or vector?

A built-in array has a fixed number of elements. A std::vector is a standard-library container that manages a resizable sequence of elements of one type. It is a strong default for a dynamic list of values.

C++17
#include <iostream>
#include <vector>

int main() {
    std::vector<int> scores{80, 92, 75};
    scores.push_back(88);
    for (int score : scores) {
        std::cout << score << '\n';
    }
}

push_back appends an element. The range-based for loop visits each element in sequence. This example prints 80, 92, 75, and 88 on separate lines.

Size and capacity

size() reports how many elements currently belong to the vector. capacity() reports how many elements can fit in the currently allocated storage before another allocation is needed. Capacity is an implementation-managed detail; do not assume a specific growth factor.

vector: [80] [92] [75]
size = 3
push_back(88)
vector: [80] [92] [75] [88]
size = 4

Access elements

Use scores[i] only when you know i is a valid index. Valid indexes are from zero through size() - 1. The member function at(i) checks the index and throws std::out_of_range if it is invalid.

Common operations

OperationPurposeTypical complexity
size()Number of elementsConstant
push_back(x)Append an elementAmortized constant
pop_back()Remove last elementConstant
at(i)Checked element accessConstant
insert / eraseInsert/remove at a positionLinear in elements shifted

Amortized constant time means a sequence of appends has constant average cost per append over the sequence, even though an individual append may allocate and move elements.

Iterator invalidation

A vector may allocate new storage when it grows. Reallocation invalidates pointers, references, and iterators to its elements. Inserting or erasing can also invalidate handles at or after the changed position. A safe beginner rule: do not keep an element pointer, reference, or iterator across an operation that may reallocate or shift elements unless you have checked the invalidation rules.

Common mistakes

  • Accessing v[v.size()]; that is one past the last element.
  • Calling pop_back() on an empty vector.
  • Assuming reserve(n) creates n elements. It changes capacity, not size.
  • Keeping a reference to an element after a possible reallocation.

Practice

  1. Create an empty vector of integers, read five values, and print their sum.
  2. Print both size and capacity before and after appending values. Do not assume capacity values in your explanation.
  3. Use at() to access an index and test an invalid index.
  4. Explain the difference between reserve(20) and resize(20).

Practice solutions

Show worked solutions
  1. #include <iostream>
    #include <vector>
    int main() {
        std::vector<int> values;
        int total = 0;
        for (int i = 0; i < 5; ++i) {
            int value;
            if (!(std::cin >> value)) return 1;
            values.push_back(value);
            total += value;
        }
        std::cout << total << '\n';
    }
  2. Print values.size() and values.capacity() before and after each push_back. Capacity is at least the size, but its growth strategy and exact values are implementation-dependent.
  3. Use values.at(index) inside a try block and catch std::out_of_range for an invalid index. Include <stdexcept> if naming that exception type.
  4. reserve(20) requests capacity for at least 20 elements without changing the vector's size. resize(20) changes the size to 20, creating or destroying elements as needed.

Check your understanding

Does reserve(10) make vector.size() equal to 10?

Answer: No. It may increase capacity so storage for at least ten elements is available, but size remains the number of actual elements.

Summary

Use vector for resizable sequences. Understand size, capacity, index bounds, and iterator invalidation. Prefer standard containers over manually managing dynamic arrays in ordinary application code.

References