Cppvector

vector

std::vector<T> is a dynamic, resizable array, and it is the default, go-to sequence container in C++. Unless you have a specific reason to reach for something else, vector should be your first choice for storing a collection of elements — it has the best combination of performance, cache-friendliness, and ease of use of any standard container.
Creating and initializing

vector_create.cpp

CPP
#include <vector>
#include <iostream>

int main() {
    std::vector<int> empty;                    // empty vector
    std::vector<int> fromList = {1, 2, 3, 4};   // initializer list
    std::vector<int> repeated(5, 0);            // five zeros: {0,0,0,0,0}
    std::vector<int> copy(fromList);            // copy of another vector

    std::cout << fromList.size() << std::endl; // 4
    return 0;
}
Adding and removing elements

vector_push_pop.cpp

CPP
#include <vector>
#include <iostream>

int main() {
    std::vector<int> nums;

    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);   // nums = {10, 20, 30}

    nums.pop_back();      // removes 30 -> nums = {10, 20}

    std::cout << nums.size() << std::endl;  // 2
    std::cout << nums.empty() << std::endl; // 0 (false)

    nums.clear();          // removes all elements
    std::cout << nums.empty() << std::endl; // 1 (true)

    return 0;
}
Accessing elements: [] vs. at()
Vectors support the familiar [] indexing operator, but it performs no bounds checking — reading or writing past the end is undefined behavior, not a caught error. .at() does the same job but checks the index and throws std::out_of_range if it's invalid.

vector_access.cpp

CPP
#include <vector>
#include <iostream>
#include <stdexcept>

int main() {
    std::vector<int> nums = {10, 20, 30};

    std::cout << nums[1] << std::endl;     // 20 — fast, unchecked

    try {
        std::cout << nums.at(10) << std::endl; // throws std::out_of_range
    } catch (const std::out_of_range& e) {
        std::cout << "Caught: " << e.what() << std::endl;
    }

    return 0;
}
operator[] does not check bounds
nums[10] on a 3-element vector will not throw — it silently reads or writes memory outside the vector's buffer, which is undefined behavior and a classic source of hard-to-diagnose bugs and security vulnerabilities. Use .at() when the index isn't already guaranteed valid (for example, when it comes from user input), and reserve [] for hot loops where you've already established the index is in range.
Iterating

vector_iterate.cpp

CPP
#include <vector>
#include <iostream>

int main() {
    std::vector<std::string> names = {"Alice", "Bob", "Carol"};

    for (const auto& name : names) {
        std::cout << name << std::endl;
    }

    return 0;
}
Amortized O(1) push_back
A vector stores its elements in one contiguous block of heap memory. When that block is full and you call push_back again, the vector must allocate a larger block (typically double the previous capacity), copy or move every existing element into it, and free the old block. That single operation is O(n) — but it happens rarely, and the cost is spread out (“amortized”) across all the cheap O(1) push_backs that happen between reallocations. Averaged over many calls, push_back behaves as if it were O(1).
reserve() — avoiding reallocations
If you know roughly how many elements you'll end up storing, calling .reserve(n) up front allocates enough capacity for n elements immediately, so subsequent push_back calls don't need to reallocate at all. This is a simple, very common performance optimization.

vector_reserve.cpp

CPP
#include <vector>
#include <iostream>

int main() {
    std::vector<int> nums;
    nums.reserve(1000);  // allocate capacity for 1000 elements up front

    for (int i = 0; i < 1000; i++) {
        nums.push_back(i); // no reallocations happen during this loop
    }

    std::cout << nums.size() << std::endl;     // 1000 (actual element count)
    std::cout << nums.capacity() << std::endl; // >= 1000 (allocated space)

    return 0;
}
size() vs. capacity()
.size() is the number of elements actually stored; .capacity() is how many elements fit in the currently allocated block before another reallocation is needed. Capacity is always greater than or equal to size.
vector is the default choice
Prefer std::vector unless you have a specific, demonstrated need for another container's characteristics (frequent insertion in the middle, insertion at the front, or key-based lookup). Its contiguous memory layout makes it by far the most cache-friendly standard container, which usually makes it faster in practice than more “theoretically appropriate” containers even for operations it's not specifically optimized for.