A practical C++ field guide. You will move from values in memory to objects and programs in motion, learning the language features that make C++ fast, expressive, and close to the hardware.

01 / Model Think close to the machine

Types, pointers, and memory are not abstract details here. They are the material of the language.

02 / Compose Build useful pieces

Functions, structs, classes, and the STL turn low-level ideas into readable programs.

03 / Coordinate Make work happen together

Threads, exceptions, and tests help programs stay predictable under pressure.

How to use this guide

Read each section in two passes: first for the concept, then for a real example. After every code sample, change one value, add one case, or break one assumption. That small experiment is where the syntax becomes intuition.

01 / Variables and Basic Types

C++ gives you direct access to memory and types that map closely to hardware. Knowing the size and behavior of each type is the foundation for everything else.

Core typesint, float, double, char, bool
Constantsconst for values that must not change at runtime
I/Ocin / cout with formatters like setw, setprecision, fixed
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    int itemCount = 5;
    double price = 10.5;
    const double TAX_RATE = 0.08;

    cout << "Item Count: " << itemCount << endl;
    cout << "Price: " << fixed << setprecision(2) << price << endl;
    cout << "Tax Rate: " << TAX_RATE << endl;

    return 0;
}

02 / Control Structures

Conditionals and loops are how a program makes decisions and repeats work. The patterns here — especially switch and loop control — show up constantly in everyday C++ code.

Decision makingif / else if / else, switch
Loopsfor, while, do-while
Controlbreak exits the loop, continue skips to the next iteration
#include <iostream>
using namespace std;

int main() {
    int scores[] = {85, 42, 91, 67, 78};
    for (int i = 0; i < 5; ++i) {
        if (scores[i] < 50) {
            cout << "Score " << scores[i] << " failed. Skipping..." << endl;
            continue;
        }
        cout << "Score " << scores[i] << " passed." << endl;
    }
    return 0;
}

03 / Arrays and Vectors

Fixed-size arrays are simple but rigid. std::vector grows dynamically — essential when you do not know how many items you will need to store at runtime.

Static arraysint arr[10], fixed at compile time
Dynamic vectorsstd::vector<T>, resizes as needed
Multi-dimensional — arrays of arrays for matrices and tables

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<double> prices = {10.5, 5.2, 8.9, 3.1};
    for (double price : prices) {
        cout << "Price: $" << price << endl;
    }
    return 0;
}

04 / Functions

Functions are how you turn a monolithic program into composable pieces. Write functions to calculate totals, validate input, and wrap repeated logic.

Pass by value — copies the argument, safe but slower for large data
Pass by referenceconst & avoids copies while preventing modification
Default arguments — optional parameters with fallback values
#include <iostream>
using namespace std;

double calculateTotal(double price, double taxRate = 0.08) {
    return price + (price * taxRate);
}

int main() {
    double total = calculateTotal(50.0);
    cout << "Total: $" << total << endl;
    return 0;
}

05 / Pointers and References

Pointers give you direct access to memory addresses — the backbone of dynamic data structures and efficient parameter passing. References offer the same power with less risk.

Declareint *ptr
Address-of&variable gets the memory address
Dereference*ptr reads or writes the value at that address
Referenceint &ref = variable, an alias that cannot be reseated
#include <iostream>
using namespace std;

void applyDiscount(double *price) {
    *price = *price * 0.9;
}

int main() {
    double price = 100.0;
    applyDiscount(&price);
    cout << "Discounted Price: $" << price << endl;
    return 0;
}

06 / Structs and Classes

Structs group related data. Classes add methods and access control. Together they let you model real-world entities — students, accounts, products — as coherent units instead of scattered variables.

Structs — public by default, best for plain data grouping
Classes — encapsulate data with private / public access
Methods — functions that belong to a type
#include <iostream>
using namespace std;

struct Student {
    int id;
    double gpa;
    void display() {
        cout << "ID: " << id << ", GPA: " << gpa << endl;
    }
};

int main() {
    Student s1 = {1, 3.8};
    s1.display();
    return 0;
}

07 / Dynamic Memory Allocation

Sometimes you need memory whose size or lifetime is not known at compile time. new and delete give you that control. Mismatch them and you get leaks or dangling pointers — two of the most common bugs in C++ programs.

Allocatenew Type for single objects, new Type[n] for arrays
Deallocatedelete for single objects, delete[] for arrays
Rule — every new must have a matching delete
#include <iostream>
using namespace std;

int main() {
    int *scores = new int[5];
    for (int i = 0; i < 5; ++i) {
        scores[i] = i * 10;
    }
    for (int i = 0; i < 5; ++i) {
        cout << scores[i] << " ";
    }
    delete[] scores;
    return 0;
}

08 / File I/O

Programs read from and write to files to persist data. The fstream family gives you the same stream interface as cin / cout, making file operations straightforward.

Streamsifstream (read), ofstream (write), fstream (both)
Pattern — open, read/write, close
Check — always verify is_open() before operating on a file
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ofstream outFile("students.txt");
    if (outFile.is_open()) {
        outFile << "Student 1: ID=1, GPA=3.8\n";
        outFile << "Student 2: ID=2, GPA=3.5\n";
        outFile.close();
    }
    return 0;
}

09 / STL — Standard Template Library

The STL provides containers, algorithms, and iterators that save you from reimplementing common patterns. vector, map, and sort cover most everyday data-handling needs.

Containersstd::queue (FIFO), std::vector (dynamic array), std::map (key-value)
Algorithmsstd::sort, std::find, std::for_each
Iterators — pointer-like objects that connect algorithms to containers
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> ages = {34, 21, 45, 19};
    sort(ages.begin(), ages.end());
    for (int age : ages) {
        cout << age << " ";
    }
    return 0;
}

10 / Object-Oriented Programming

OOP lets you model complex systems as interacting objects. Use inheritance to specialize types, polymorphism to swap behavior, and encapsulation to protect internal state.

Encapsulation — hide implementation details behind a public interface
Inheritance — extend a base class with specialized behavior
Polymorphism — call the correct derived method through a base pointer using virtual
#include <iostream>
using namespace std;

class Shape {
private:
    string name;
public:
    Shape(string n) : name(n) {}
    virtual void describe() {
        cout << "Shape: " << name << endl;
    }
};

class Circle : public Shape {
public:
    Circle() : Shape("Circle") {}
    void describe() override {
        cout << "A round shape with no corners." << endl;
    }
};

int main() {
    Shape *s = new Circle();
    s->describe();
    delete s;
    return 0;
}

11 / Threading and Concurrency

Many programs benefit from doing multiple things at once. C++11 introduced std::thread and synchronization primitives so you can write concurrent code without dropping to platform-specific APIs.

Threadsstd::thread launches concurrent execution
Joint.join() waits for a thread to finish
Mutexstd::mutex protects shared data from race conditions
Condition variablestd::condition_variable for thread signaling
#include <iostream>
#include <thread>
using namespace std;

void printMessage(string msg) {
    cout << "Message: " << msg << endl;
}

int main() {
    thread t1(printMessage, "Hello from thread 1");
    thread t2(printMessage, "Hello from thread 2");
    t1.join();
    t2.join();
    return 0;
}

12 / Exception Handling

Input can be invalid. Files can go missing. Memory can run out. Exception handling gives you a structured way to respond to errors instead of checking return codes everywhere.

Try / catch / throw — the core mechanism
Standard exceptionsinvalid_argument, runtime_error, out_of_range
Custom exceptions — extend std::exception for domain-specific errors
#include <iostream>
#include <stdexcept>
using namespace std;

void validateAge(int age) {
    if (age <= 0) {
        throw invalid_argument("Invalid age");
    }
    cout << "Valid age: " << age << endl;
}

int main() {
    try {
        validateAge(-5);
    } catch (const invalid_argument &e) {
        cerr << "Error: " << e.what() << endl;
    }
    return 0;
}

13 / Debugging and Testing

Bugs are hard to reproduce and expensive to fix once code ships. Catch them early with compiler warnings, assertions, and systematic testing.

Compiler warnings — enable -Wall -Wextra, treat warnings as errors
Common bugs — off-by-one errors, null pointer dereferences, uninitialized variables
Assertionsassert() catches logic errors at runtime during development
#include <iostream>
#include <cassert>
using namespace std;

double calculateTotal(double price, double taxRate) {
    return price + (price * taxRate);
}

int main() {
    assert(calculateTotal(100.0, 0.1) == 110.0);
    cout << "Test passed!" << endl;
    return 0;
}

14 / Summary

You now have the vocabulary to read a small C++ program: data has a type, work has a control path, memory has an owner, and concurrent work needs coordination. Keep this page nearby as a reference while you build.

Concept What to remember
Types & variables Know your sizes, use const for constants
Control flow switch for dispatch, break/continue for loop control
Vectors Prefer std::vector over raw arrays
Functions Use const & for large parameters
Pointers Every new needs a delete
OOP virtual for polymorphism, private for encapsulation
STL queue, vector, sort cover most everyday needs
Threading std::thread + std::mutex for concurrency
Exceptions Wrap risky operations in try/catch
Debugging -Wall, assert(), initialize everything