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
| Type | Size (typical) | Range | Example |
|---|---|---|---|
int | 4 bytes | -2.1B to 2.1B | int age = 25; |
long long | 8 bytes | ±9.2 quintillion | long long big = 9000000000LL; |
double | 8 bytes | ±1.7×10³⁰⁸ (15 digits) | double pi = 3.14159265; |
float | 4 bytes | ±3.4×10³⁸ (7 digits) | float f = 2.5f; |
char | 1 byte | -128 to 127 / ASCII | char letter = 'A'; |
bool | 1 byte | true or false | bool active = true; |
std::string | varies | dynamic text | std::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
constby default: Mark variablesconstunless you need to modify them. This prevents bugs and enables compiler optimizations. - Prefer
{}initialization: Brace initialization prevents accidental narrowing conversions. - Use
autowisely: 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::stringover C strings:std::stringmanages memory automatically and provides useful methods. - Use
constexprfor compile-time constants: Preferconstexprover#definemacros 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.