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++ Variables and Data Types

Variables store data in memory. C++ is statically typed — every variable must have a declared type that determines how much memory it occupies and what operations are valid on it.

Fundamental Data Types

TypeSize (typical)RangeExample
int4 bytes-2.1B to 2.1Bint age = 25;
long long8 bytes±9.2 quintillionlong long big = 9000000000LL;
double8 bytes±1.7×10³⁰⁸ (15 digits)double pi = 3.14159265;
float4 bytes±3.4×10³⁸ (7 digits)float f = 2.5f;
char1 byte-128 to 127 / ASCIIchar letter = 'A';
bool1 bytetrue or falsebool active = true;
std::stringvariesdynamic textstd::string s = "hello";

Declaring and Initializing Variables

variables.cpp
#include <iostream>
#include <string>

int main() {
    // Declaration with initialization
    int count = 10;
    double price = 19.99;
    char grade = 'A';
    bool is_valid = true;
    std::string name = "Alice";

    // Modern initialization styles (C++11)
    int x{42};           // brace initialization (prevents narrowing)
    double y{3.14};
    std::string city{"Tokyo"};

    // Multiple declarations
    int a = 1, b = 2, c = 3;

    // Uninitialized — contains garbage! Avoid this.
    int danger;  // value is undefined

    std::cout << name << " lives in " << city << "
";
    std::cout << "Count: " << count << ", Price: $" << price << "
";
    return 0;
}

const, constexpr, and auto

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

int main() {
    // const — value cannot be changed after initialization
    const int MAX_SIZE = 100;
    const double TAX_RATE = 0.08;
    // MAX_SIZE = 200;  // ERROR: assignment to const variable

    // constexpr — computed at compile time (C++11)
    constexpr int DAYS_IN_WEEK = 7;
    constexpr double PI = 3.14159265358979;
    constexpr int HOURS = DAYS_IN_WEEK * 24;  // 168, computed at compile time

    // auto — compiler deduces the type (C++11)
    auto count = 42;          // int
    auto pi = 3.14;           // double
    auto message = "hello";   // const char* (not std::string!)
    auto name = std::string("Alice");  // std::string

    // auto is most useful with complex types
    std::vector<int> numbers{1, 2, 3, 4, 5};
    for (auto n : numbers) {  // auto = int
        std::cout << n << " ";
    }
    std::cout << "
";

    return 0;
}

Type Conversion and Casting

casting.cpp
#include <iostream>

int main() {
    // Implicit conversion (widening — safe)
    int i = 42;
    double d = i;  // int → double: 42.0

    // Implicit narrowing (may lose data — WARNING)
    double pi = 3.14159;
    int truncated = pi;  // 3 (decimal part lost!)
    // int safe = {pi};  // ERROR with brace init (prevents narrowing)

    // Explicit casting (C++ style — preferred)
    double result = static_cast<double>(10) / 3;  // 3.333...
    int rounded = static_cast<int>(pi + 0.5);     // 3

    // String to number
    #include <string>
    std::string num_str = "42";
    int num = std::stoi(num_str);      // string to int
    double dbl = std::stod("3.14");    // string to double

    // Number to string
    std::string s = std::to_string(42);     // "42"
    std::string s2 = std::to_string(3.14);  // "3.140000"

    std::cout << "Result: " << result << "
";
    return 0;
}

Scope and Lifetime

scope.cpp
#include <iostream>

int global_var = 100;  // global scope — accessible everywhere

int main() {
    int local_var = 50;  // local to main

    {
        int block_var = 25;  // local to this block
        std::cout << block_var << "
";  // OK
    }
    // std::cout << block_var;  // ERROR: out of scope

    // Variables in loops are local to the loop
    for (int i = 0; i < 3; ++i) {
        int temp = i * 10;
        std::cout << temp << " ";
    }
    // std::cout << i;     // ERROR: i is out of scope
    // std::cout << temp;  // ERROR: temp is out of scope

    std::cout << "
Global: " << global_var << "
";
    return 0;
}

Best Practices

  • Always initialize variables: Uninitialized variables contain garbage values and cause undefined behavior.
  • Use const by default: Mark variables const unless you need to modify them. This prevents bugs and enables compiler optimizations.
  • Prefer {} initialization: Brace initialization prevents accidental narrowing conversions.
  • Use auto wisely: Great for complex types and iterators, but avoid when the type is not obvious from context.
  • Declare variables close to first use: Unlike C, C++ allows declaring variables anywhere. Declare them in the smallest possible scope.
  • Use std::string over C strings: std::string manages memory automatically and provides useful methods.
  • Use constexpr for compile-time constants: Prefer constexpr over #define macros for type safety.

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.