Arrays, std::array & std::vector

অ্যারে — পুরনো থেকে আধুনিক

Read: ~35 min 18 practice problems

1. C-style Arrays — The Old Way

carr.cpp
#include <iostream>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    for (int i = 0; i < 5; ++i) std::cout << arr[i] << " ";
    std::cout << "\n";
    std::cout << "size in bytes = " << sizeof(arr) << "\n";
}
No bounds checking arr[10] on a 5-element array is undefined behavior. C-arrays decay to pointers when passed to functions, losing size info. Avoid in modern code.

2. std::array — Compile-time Size

A safer wrapper around a fixed-size array. Knows its size, doesn't decay, supports STL operations.

std_array.cpp
#include <iostream>
#include <array>

int main() {
    std::array<int, 5> a = {10, 20, 30, 40, 50};
    for (int x : a) std::cout << x << " ";
    std::cout << "\nsize = " << a.size() << "\n";
    std::cout << "first = " << a.front() << "\n";
    std::cout << "last = "  << a.back()  << "\n";
    // std::cout << a.at(10);  // throws std::out_of_range
}

3. std::vector — Dynamic Size

A growable array. Most-used C++ container. Default choice unless you have a reason otherwise.

vector.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v;            // empty
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.emplace_back(4);            // constructs in-place

    std::cout << "size = " << v.size()
              << ", capacity = " << v.capacity() << "\n";

    for (int x : v) std::cout << x << " ";
    std::cout << "\n";
}

4. When to Use Which

ContainerSizeMemoryUse when
C-arrayFixed, compile-timeStackAlmost never (legacy)
std::array<T,N>Fixed, compile-timeStackKnown size, want STL features
std::vector<T>DynamicHeapDefault. Size unknown or growing

5. 2D Arrays

matrix.cpp
#include <iostream>
#include <vector>

int main() {
    std::vector<std::vector<int>> mat(3, std::vector<int>(4, 0));
    mat[1][2] = 42;

    for (const auto& row : mat) {
        for (int x : row) std::cout << x << " ";
        std::cout << "\n";
    }
}

6. Practice Problems

  1. Create a vector of 10 zeros.
    ✨ Show Answer
    std::vector<int> v(10, 0);
  2. Sum all elements in a vector.
    ✨ Show Answer
    int s = 0;
    for (int x : v) s += x;
  3. Find the max element.
    ✨ Show Answer
    #include <algorithm>
    int m = *std::max_element(v.begin(), v.end());
  4. Difference between v[i] and v.at(i)?
    ✨ Show Answer

    v[i] — no bounds check (faster, undefined behavior on out-of-range). v.at(i) — throws std::out_of_range. Use at() when index comes from external input.

  5. Reverse a vector in place.
    ✨ Show Answer
    std::reverse(v.begin(), v.end());
  6. Why does vector double its capacity on growth?
    ✨ Show Answer

    To make push_back amortized O(1). Doubling means the total work over N inserts is O(N), not O(N²) (which copying once per insert would give).

  7. What's the size of sizeof(arr) for int arr[5]?
    ✨ Show Answer

    20 bytes on a typical 32-bit-int system (5 × 4).

  8. Build a 5×5 multiplication table as a std::vector<std::vector<int>>.
    ✨ Show Answer
    std::vector<std::vector<int>> t(5, std::vector<int>(5));
    for (int i = 0; i < 5; ++i)
        for (int j = 0; j < 5; ++j)
            t[i][j] = (i+1) * (j+1);
  9. Demo: vector decay vs std::array preserving size when passed.
    ✨ Show Answer

    C-array: void f(int a[]) — a is a pointer, no size.
    std::array: void f(std::array<int,5>& a) — size is part of the type.
    std::vector: v.size() always available.

  10. Difference between push_back and emplace_back?
    ✨ Show Answer

    push_back(x) copies/moves x into the container. emplace_back(args...) constructs the element in place using the args. Saves a move/copy for complex types.

  11. Insert 99 at position 2 in a vector.
    ✨ Show Answer
    v.insert(v.begin() + 2, 99);
  12. Remove element at index 3.
    ✨ Show Answer
    v.erase(v.begin() + 3);
  13. Why prefer std::vector over std::list usually?
    ✨ Show Answer

    Vector is contiguous in memory → cache-friendly. List has scattered nodes with overhead per element. Vector wins almost always for traversal, even with insertions in the middle.

  14. Print elements of std::array<int,3>{1,2,3} with range-for.
    ✨ Show Answer
    std::array<int, 3> a = {1,2,3};
    for (int x : a) std::cout << x << " ";
  15. Reserve capacity 1000 for a vector before pushing.
    ✨ Show Answer
    v.reserve(1000); // avoids reallocation
  16. Difference between resize and reserve?
    ✨ Show Answer

    resize(n) changes the actual size (creates default elements if growing). reserve(n) only changes capacity — size stays the same.

  17. Does std::vector<bool> behave like other vectors?
    ✨ Show Answer

    No! It's specialized to pack bits. v[i] returns a proxy, not bool&. This breaks generic code. Prefer std::vector<char> or std::deque<bool> when you need a real container of bools.

  18. Clear all elements but keep the capacity.
    ✨ Show Answer
    v.clear(); // size becomes 0, capacity unchanged

Summary

Modern C++ has three array types. Use std::vector by default; std::array for fixed sizes; raw C-arrays only for legacy interop. Vectors grow by doubling for amortized O(1) append. Use at() for bounds-checked access, [] for fast unchecked access.

Next Module → Pointers: Indirection, nullptr, Smart Pointer Preview.