C++ Tutorial
C++ is a general-purpose, high-performance programming language with low-level memory control and high-level OOP features. It's used for systems programming, game engines, embedded systems, competitive programming, and performance-critical applications.
Syntax & Structure
C++
#include <iostream>
#include <string>
using namespace std;
int main() {
// Output
cout << "Hello, World!" << endl;
cerr << "Error message" << endl; // stderr
// Input
string name;
cout << "Enter name: ";
cin >> name;
cin.ignore(); // clear newline
getline(cin, name); // read full line
cout << "Hello, " << name << "!\n";
return 0; // 0 = success
}
// Compile and run
// g++ -std=c++17 -o hello main.cpp
// ./hello
Data Types
| Type | Size | Example |
|---|---|---|
int | 4 bytes | int n = 42; |
long long | 8 bytes | long long big = 1e18; |
float | 4 bytes | float f = 3.14f; |
double | 8 bytes | double d = 3.14; |
char | 1 byte | char c = 'A'; |
bool | 1 byte | bool ok = true; |
string | variable | string s = "hello"; |
auto | deduced | auto x = 42.0; |
Pointers & References
C++
int x = 10;
// Pointer - stores memory address
int* ptr = &x; // &x = address of x
cout << ptr; // prints address (e.g. 0x7ffff...)
cout << *ptr; // dereference: prints 10
*ptr = 20; // modifies x through pointer
cout << x; // 20
// Reference - alias for a variable
int& ref = x; // ref is another name for x
ref = 30;
cout << x; // 30
// Pointer arithmetic
int arr[] = {10, 20, 30};
int* p = arr;
cout << *(p + 1); // 20
// nullptr (C++11)
int* np = nullptr;
if (np) { ... } // safe null check
// const pointer vs pointer to const
const int* cp = &x; // cannot change value: *cp = 5; // error
int* const pc = &x; // cannot change address: pc = &y; // error
const int* const cpc = &x; // neither
Functions
C++
// Basic function
int add(int a, int b) { return a + b; }
// Default parameters
int power(int base, int exp = 2) {
int result = 1;
for (int i = 0; i < exp; i++) result *= base;
return result;
}
// Pass by reference (modify original)
void swap(int& a, int& b) {
int temp = a; a = b; b = temp;
}
// Pass by const reference (read-only, no copy)
void print(const string& s) { cout << s; }
// Function overloading
double add(double a, double b) { return a + b; }
string add(string a, string b) { return a + b; }
// Inline function (hint to compiler)
inline int square(int x) { return x * x; }
// Template function
template <typename T>
T maxOf(T a, T b) { return (a > b) ? a : b; }
maxOf(3, 5); // int
maxOf(3.14, 2.71); // double
maxOf(string("a"), string("b")); // string
// Variadic template (C++11)
template<typename... Args>
void printAll(Args... args) { (cout << ... << args) << "\n"; }
Classes & Objects
C++
class Animal {
private:
string name;
int age;
public:
// Constructor with initializer list
Animal(string name, int age) : name(name), age(age) {}
// Destructor
~Animal() { cout << name << " destroyed\n"; }
// Getters
string getName() const { return name; }
int getAge() const { return age; }
// Virtual method (for polymorphism)
virtual string speak() const { return name + " makes a sound"; }
// Operator overloading
bool operator==(const Animal& other) const {
return name == other.name;
}
// Friend function
friend ostream& operator<<(ostream& os, const Animal& a) {
return os << a.name << " (age " << a.age << ")";
}
};
// Inheritance
class Dog : public Animal {
private:
string breed;
public:
Dog(string name, int age, string breed)
: Animal(name, age), breed(breed) {}
string speak() const override {
return getName() + " says Woof!";
}
};
// Usage
Dog d("Rex", 3, "Labrador");
cout << d << "\n"; // Rex (age 3)
cout << d.speak() << "\n"; // Rex says Woof!
// Polymorphism - base pointer to derived object
Animal* a = new Dog("Buddy", 2, "Beagle");
cout << a->speak(); // calls Dog::speak (virtual dispatch)
delete a;
STL Containers
C++
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <queue>
#include <stack>
#include <algorithm>
// vector (dynamic array)
vector<int> v = {3, 1, 4, 1, 5};
v.push_back(9);
v.pop_back();
v[0]; // 3
v.size(); // 5
v.empty(); // false
v.front(); v.back();
sort(v.begin(), v.end()); // ascending
sort(v.begin(), v.end(), greater<int>()); // descending
// map (sorted key-value pairs)
map<string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 82;
for (auto& [key, val] : scores) { // structured bindings (C++17)
cout << key << ": " << val;
}
// unordered_map (hash map, O(1) average)
unordered_map<string, int> freq;
freq["apple"]++; freq["banana"]++;
// set (sorted unique values)
set<int> s = {1, 2, 2, 3}; // {1, 2, 3}
// queue (FIFO)
queue<int> q;
q.push(1); q.push(2);
q.front(); // 1
q.pop(); // removes 1
// stack (LIFO)
stack<int> st;
st.push(5); st.push(10);
st.top(); // 10
st.pop();
// Algorithms
vector<int> nums = {5, 3, 8, 1};
sort(nums.begin(), nums.end());
auto it = lower_bound(nums.begin(), nums.end(), 3); // binary search
int mx = *max_element(nums.begin(), nums.end());
int sum = accumulate(nums.begin(), nums.end(), 0);
Smart Pointers (C++11+)
C++
#include <memory>
// unique_ptr - exclusive ownership, auto-deleted
unique_ptr<int> up = make_unique<int>(42);
cout << *up; // 42
// deleted automatically when goes out of scope
// shared_ptr - shared ownership, reference counted
shared_ptr<string> sp1 = make_shared<string>("hello");
shared_ptr<string> sp2 = sp1; // both own the string
cout << sp1.use_count(); // 2
// deleted when last shared_ptr goes out of scope
// weak_ptr - non-owning reference (avoid circular refs)
weak_ptr<string> wp = sp1;
if (auto locked = wp.lock()) { // check if still alive
cout << *locked;
}
Best Practice: Prefer smart pointers over raw
new/delete in modern C++. Use unique_ptr by default, shared_ptr when shared ownership is needed.Memory Management
C++ gives you direct control over memory, which is powerful but dangerous if you ignore ownership rules.
- Prefer stack allocation where possible.
- Use
std::vector,std::string, and RAII types instead of manual arrays. - Prefer
std::unique_ptrandstd::shared_ptrover raw owning pointers. - Avoid memory leaks, double deletes, and dangling pointers.
Algorithms Library
The Standard Library includes algorithms that are faster to write and easier to review than hand-coded loops.
C++
#include <algorithm>
#include <vector>
std::vector<int> scores{4, 8, 1, 7, 3};
std::sort(scores.begin(), scores.end());
bool hasEight = std::find(scores.begin(), scores.end(), 8) != scores.end();
Build & Debug
Students should understand how code becomes an executable: preprocessing, compiling, linking, then debugging when things go wrong.
Terminal
g++ -std=c++20 -Wall -Wextra main.cpp -o app
./app