C++ Programming Tutorial

Learn modern C++ step-by-step — from basics to advanced features like templates, STL, and smart pointers. Clear explanations with practical, runnable examples.

C++ Arrays and Vectors

C++ offers three main sequential containers: C-style arrays (fixed, unsafe), std::array (fixed, safe), and std::vector (dynamic, safe). Modern C++ strongly favors std::vector for most use cases.

C-Style Arrays

c_arrays.cpp
#include <iostream>

int main() {
    // Fixed-size, stack-allocated
    int numbers[5] = {10, 20, 30, 40, 50};

    // Access by index (0-based)
    std::cout << numbers[0] << "
";  // 10
    std::cout << numbers[4] << "
";  // 50

    // Iterate
    for (int i = 0; i < 5; ++i) {
        std::cout << numbers[i] << " ";
    }
    std::cout << "
";

    // WARNING: no bounds checking!
    // numbers[10] = 99;  // undefined behavior — may crash or corrupt memory

    // Size must be known at compile time
    constexpr int SIZE = 3;
    double values[SIZE] = {1.1, 2.2, 3.3};

    return 0;
}

std::array (C++11) — Fixed Size, Safe

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

int main() {
    // Type-safe, knows its own size, supports STL algorithms
    std::array<int, 5> nums{10, 20, 30, 40, 50};

    std::cout << "Size: " << nums.size() << "
";   // 5
    std::cout << "First: " << nums.front() << "
"; // 10
    std::cout << "Last: " << nums.back() << "
";   // 50

    // Bounds-checked access with .at()
    // nums.at(10);  // throws std::out_of_range

    // Works with algorithms
    std::sort(nums.begin(), nums.end());
    std::reverse(nums.begin(), nums.end());

    // Range-based for
    for (int n : nums) {
        std::cout << n << " ";
    }
    std::cout << "
";

    return 0;
}

std::vector — Dynamic Size (Most Used)

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

int main() {
    // Create and initialize
    std::vector<int> nums{1, 2, 3, 4, 5};
    std::vector<std::string> names{"Alice", "Bob", "Charlie"};
    std::vector<double> zeros(10, 0.0);  // 10 elements, all 0.0

    // Add elements
    nums.push_back(6);
    nums.push_back(7);
    nums.emplace_back(8);  // construct in-place (more efficient)

    // Access elements
    std::cout << nums[0] << "
";      // 1 (no bounds check)
    std::cout << nums.at(2) << "
";   // 3 (throws if out of range)
    std::cout << nums.front() << "
"; // 1
    std::cout << nums.back() << "
";  // 8

    // Size and capacity
    std::cout << "Size: " << nums.size() << "
";
    std::cout << "Empty: " << nums.empty() << "
";

    // Remove elements
    nums.pop_back();  // remove last
    nums.erase(nums.begin() + 1);  // remove at index 1

    // Insert
    nums.insert(nums.begin(), 0);  // insert 0 at front

    // Iterate
    for (const auto& n : nums) {
        std::cout << n << " ";
    }
    std::cout << "
";

    // Sort
    std::sort(nums.begin(), nums.end());

    // Find
    auto it = std::find(nums.begin(), nums.end(), 5);
    if (it != nums.end()) {
        std::cout << "Found 5 at index " << (it - nums.begin()) << "
";
    }

    return 0;
}

Common Vector Operations

vector_ops.cpp
#include <iostream>
#include <vector>
#include <numeric>    // for accumulate
#include <algorithm>  // for sort, min/max_element, count

int main() {
    std::vector<int> v{5, 2, 8, 1, 9, 3, 7};

    // Sum all elements
    int sum = std::accumulate(v.begin(), v.end(), 0);
    std::cout << "Sum: " << sum << "
";  // 35

    // Min and max
    auto [min_it, max_it] = std::minmax_element(v.begin(), v.end());
    std::cout << "Min: " << *min_it << ", Max: " << *max_it << "
";

    // Count occurrences
    int count = std::count(v.begin(), v.end(), 5);

    // Remove duplicates (sort first)
    std::sort(v.begin(), v.end());
    v.erase(std::unique(v.begin(), v.end()), v.end());

    // Filter: keep only values > 3
    std::vector<int> filtered;
    std::copy_if(v.begin(), v.end(), std::back_inserter(filtered),
                 [](int x) { return x > 3; });

    for (int n : filtered) std::cout << n << " ";  // 5 7 8 9
    std::cout << "
";

    return 0;
}

Comparison Table

FeatureC arraystd::arraystd::vector
SizeFixed (compile-time)Fixed (compile-time)Dynamic (runtime)
Bounds checkingNone.at() method.at() method
Knows its sizeNoYes (.size())Yes (.size())
STL compatiblePartiallyYesYes
MemoryStackStackHeap (auto-managed)
When to useRarely (legacy code)Fixed collectionsAlmost everything
  • Default to std::vector — it handles 95% of sequential container needs.
  • Use std::array when the size is known at compile time and you want stack allocation.
  • Avoid C-style arrays in new code — they decay to pointers and lose size information.
  • Reserve capacity with v.reserve(n) if you know the approximate size upfront to avoid reallocations.

Keep Practicing

Use the online compiler to run every example and experiment with modifications. The best way to learn C++ is by writing code — even small programs build strong foundations.