Getting started
Introduction
Modern C++ (C++11/14/17/20/23) with STL, smart pointers, and move semantics.
Hello World
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
Compile: g++ -std=c++20 main.cpp -o main
Basic Types
// Integers
int x = 42;
long long y = 1000000LL;
unsigned int z = 100u;
// Floating point
float f = 3.14f;
double d = 3.14159;
// Boolean
bool flag = true;
// Character
char c = 'A';
// Auto type deduction (C++11)
auto a = 42; // int
auto b = 3.14; // double
auto c = "hello"; // const char*
Variables
// Declaration
int x;
// Initialization
int y = 10;
int z(10);
int w{10}; // Uniform initialization (C++11)
// Constants
const int MAX = 100;
constexpr int SIZE = 50; // Compile-time constant
// References
int& ref = x;
// Pointers
int* ptr = &x;
Operators
| Operator | Description |
| ------------------- | ------------------- | ------- | ------- |
| + - * / | Arithmetic |
| % | Modulo |
| ++ -- | Increment/Decrement |
| == != < > | Comparison |
| <= >= | Comparison |
| && | | ! | Logical |
| & | ^ ~ | Bitwise |
| << >> | Bit shift |
| = | Assignment |
| += -= *= /= | Compound assignment |
Control Flow
If Statement
if (x > 0) {
// positive
} else if (x < 0) {
// negative
} else {
// zero
}
// If with initializer (C++17)
if (auto it = map.find(key); it != map.end()) {
// use it
}
Switch Statement
switch (value) {
case 1:
// code
break;
case 2:
case 3:
// multiple cases
break;
default:
// default case
break;
}
// Switch with initializer (C++17)
switch (auto val = getValue(); val) {
case 1: break;
default: break;
}
Loops
// For loop
for (int i = 0; i < 10; ++i) {
// code
}
// Range-based for (C++11)
std::vector<int> vec = {1, 2, 3};
for (const auto& item : vec) {
// code
}
// While loop
while (condition) {
// code
}
// Do-while loop
do {
// code
} while (condition);
Loop Control
// Break - exit loop
for (int i = 0; i < 10; ++i) {
if (i == 5) break;
}
// Continue - skip iteration
for (int i = 0; i < 10; ++i) {
if (i % 2 == 0) continue;
}
Functions
Basic Functions
// Declaration
int add(int a, int b);
// Definition
int add(int a, int b) {
return a + b;
}
// Inline function
inline int square(int x) {
return x * x;
}
// Default parameters
void print(int x, int y = 0) {
std::cout << x << " " << y;
}
Function Overloading
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
// Different number of parameters
int add(int a, int b, int c) {
return a + b + c;
}
Lambda Functions
// Basic lambda (C++11)
auto lambda = []() {
std::cout << "Hello";
};
// With parameters
auto add = [](int a, int b) {
return a + b;
};
// Capture by value
int x = 10;
auto f1 = [x]() { return x; };
// Capture by reference
auto f2 = [&x]() { x++; };
// Capture all by value
auto f3 = [=]() { return x; };
// Capture all by reference
auto f4 = [&]() { x++; };
// Generic lambda (C++14)
auto f5 = [](auto a, auto b) {
return a + b;
};
Function Templates
// Function template
template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
// Usage
int i = max(10, 20);
double d = max(3.14, 2.72);
// Multiple type parameters
template<typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {
return a + b;
}
// Abbreviated function template (C++20)
auto add(auto a, auto b) {
return a + b;
}
Classes & Objects
Basic Class
class Rectangle {
public:
// Constructor
Rectangle(int w, int h)
: width(w), height(h) {}
// Member function
int area() const {
return width * height;
}
// Getter
int getWidth() const { return width; }
// Setter
void setWidth(int w) { width = w; }
private:
int width;
int height;
};
// Usage
Rectangle rect(10, 20);
int a = rect.area();
Constructors
class MyClass {
public:
// Default constructor
MyClass() = default;
// Parameterized constructor
MyClass(int x) : value(x) {}
// Copy constructor
MyClass(const MyClass& other)
: value(other.value) {}
// Move constructor (C++11)
MyClass(MyClass&& other) noexcept
: value(std::move(other.value)) {}
// Delegating constructor (C++11)
MyClass() : MyClass(0) {}
private:
int value;
};
Destructor
class Resource {
public:
Resource() {
// Acquire resource
ptr = new int[100];
}
~Resource() {
// Release resource
delete[] ptr;
}
private:
int* ptr;
};
Inheritance
class Animal {
public:
virtual void speak() const {
std::cout << "Some sound";
}
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void speak() const override {
std::cout << "Woof!";
}
};
// Usage
Animal* animal = new Dog();
animal->speak(); // "Woof!"
delete animal;
Access Specifiers
| Specifier | Description |
|---|---|
public |
Accessible from anywhere |
protected |
Accessible from class and derived classes |
private |
Accessible only from class |
Special Members
class MyClass {
public:
// Default constructor
MyClass() = default;
// Copy constructor
MyClass(const MyClass&) = default;
// Copy assignment
MyClass& operator=(const MyClass&) = default;
// Move constructor (C++11)
MyClass(MyClass&&) = default;
// Move assignment (C++11)
MyClass& operator=(MyClass&&) = default;
// Destructor
~MyClass() = default;
// Delete copy constructor
MyClass(const MyClass&) = delete;
};
Templates
Class Templates
template<typename T>
class Stack {
public:
void push(const T& item) {
items.push_back(item);
}
T pop() {
T item = items.back();
items.pop_back();
return item;
}
bool empty() const {
return items.empty();
}
private:
std::vector<T> items;
};
// Usage
Stack<int> intStack;
intStack.push(10);
int x = intStack.pop();
Template Specialization
// Primary template
template<typename T>
class MyClass {
public:
void print() {
std::cout << "Generic";
}
};
// Full specialization
template<>
class MyClass<int> {
public:
void print() {
std::cout << "Integer";
}
};
// Partial specialization
template<typename T>
class MyClass<T*> {
public:
void print() {
std::cout << "Pointer";
}
};
Variadic Templates
// C++11 variadic templates
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << '\n'; // C++17 fold expression
}
// Recursive variadic template
template<typename T>
void printRecursive(T value) {
std::cout << value << '\n';
}
template<typename T, typename... Args>
void printRecursive(T first, Args... rest) {
std::cout << first << ", ";
printRecursive(rest...);
}
// Usage
print(1, 2, 3, "hello");
Concepts (C++20)
// Define concept
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
// Use concept
template<Numeric T>
T add(T a, T b) {
return a + b;
}
// Concept with requires
template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
};
STL Containers
Vector
#include <vector>
// Declaration
std::vector<int> vec;
std::vector<int> vec2 = {1, 2, 3};
std::vector<int> vec3(10); // 10 elements
std::vector<int> vec4(10, 5); // 10 elements, all 5
// Operations
vec.push_back(10);
vec.pop_back();
vec.insert(vec.begin(), 5);
vec.erase(vec.begin());
vec.clear();
// Access
int x = vec[0];
int y = vec.at(1); // with bounds checking
int z = vec.front();
int w = vec.back();
// Size
size_t size = vec.size();
bool empty = vec.empty();
vec.resize(20);
Map
#include <map>
// Declaration
std::map<std::string, int> map;
// Operations
map["key"] = 42;
map.insert({"key2", 100});
map.erase("key");
// Access
int value = map["key"];
auto it = map.find("key");
if (it != map.end()) {
int val = it->second;
}
// Iteration
for (const auto& [key, value] : map) {
// C++17 structured bindings
}
Unordered Map
#include <unordered_map>
// Faster lookup than map (O(1) vs O(log n))
std::unordered_map<std::string, int> umap;
umap["key"] = 42;
auto it = umap.find("key");
// Check existence
if (umap.count("key") > 0) {
// exists
}
// C++20 contains
if (umap.contains("key")) {
// exists
}
Set
#include <set>
// Declaration
std::set<int> set;
std::set<int> set2 = {1, 2, 3};
// Operations
set.insert(10);
set.erase(10);
set.clear();
// Check membership
if (set.count(10) > 0) {
// exists
}
// C++20 contains
if (set.contains(10)) {
// exists
}
// Iteration (sorted order)
for (const auto& item : set) {
// process item
}
Other Containers
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <array>
// Deque (double-ended queue)
std::deque<int> deque;
deque.push_front(1);
deque.push_back(2);
// List (doubly-linked list)
std::list<int> list;
list.push_front(1);
list.push_back(2);
// Queue
std::queue<int> queue;
queue.push(1);
int x = queue.front();
queue.pop();
// Stack
std::stack<int> stack;
stack.push(1);
int y = stack.top();
stack.pop();
// Array (C++11)
std::array<int, 5> arr = {1, 2, 3, 4, 5};
STL Algorithms
Sorting & Searching
#include <algorithm>
#include <vector>
std::vector<int> vec = {3, 1, 4, 1, 5};
// Sort
std::sort(vec.begin(), vec.end());
// Sort with custom comparator
std::sort(vec.begin(), vec.end(),
[](int a, int b) { return a > b; });
// Binary search (requires sorted)
bool found = std::binary_search(
vec.begin(), vec.end(), 3);
// Find
auto it = std::find(vec.begin(), vec.end(), 4);
if (it != vec.end()) {
// found
}
// Find with predicate
auto it2 = std::find_if(vec.begin(), vec.end(),
[](int x) { return x > 3; });
Transformations
#include <algorithm>
#include <vector>
std::vector<int> vec = {1, 2, 3};
std::vector<int> result(3);
// Transform
std::transform(vec.begin(), vec.end(),
result.begin(),
[](int x) { return x * 2; });
// For each
std::for_each(vec.begin(), vec.end(),
[](int x) { std::cout << x; });
// Copy
std::copy(vec.begin(), vec.end(),
result.begin());
// Copy if
std::copy_if(vec.begin(), vec.end(),
result.begin(),
[](int x) { return x > 1; });
Numeric Operations
#include <numeric>
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
// Sum (C++17)
int sum = std::accumulate(
vec.begin(), vec.end(), 0);
// Product
int product = std::accumulate(
vec.begin(), vec.end(), 1,
std::multiplies<int>());
// Inner product
std::vector<int> vec2 = {1, 2, 3, 4, 5};
int dot = std::inner_product(
vec.begin(), vec.end(),
vec2.begin(), 0);
// Partial sum
std::vector<int> result(5);
std::partial_sum(vec.begin(), vec.end(),
result.begin());
Other Algorithms
// Min/Max
int min = std::min(a, b);
int max = std::max(a, b);
auto [min, max] = std::minmax(a, b); // C++17
// Min/Max element
auto it = std::min_element(vec.begin(), vec.end());
auto it2 = std::max_element(vec.begin(), vec.end());
// Count
int count = std::count(vec.begin(), vec.end(), 3);
int count2 = std::count_if(vec.begin(), vec.end(),
[](int x) { return x > 2; });
// Reverse
std::reverse(vec.begin(), vec.end());
// Unique (remove consecutive duplicates)
auto last = std::unique(vec.begin(), vec.end());
vec.erase(last, vec.end());
Smart Pointers
unique_ptr
#include <memory>
// Create unique_ptr
auto ptr = std::make_unique<int>(42);
// Access
int value = *ptr;
// Release ownership
int* raw = ptr.release();
// Reset
ptr.reset(new int(100));
// Move ownership
auto ptr2 = std::move(ptr);
// ptr is now nullptr
// Custom deleter
auto deleter = [](int* p) {
std::cout << "Deleting\n";
delete p;
};
std::unique_ptr<int, decltype(deleter)>
ptr3(new int(42), deleter);
shared_ptr
#include <memory>
// Create shared_ptr
auto ptr = std::make_shared<int>(42);
// Copy (increases reference count)
auto ptr2 = ptr;
// Reference count
long count = ptr.use_count();
// Access
int value = *ptr;
// Reset
ptr.reset();
// Create from unique_ptr
auto uptr = std::make_unique<int>(42);
std::shared_ptr<int> sptr = std::move(uptr);
weak_ptr
#include <memory>
// Create from shared_ptr
auto sptr = std::make_shared<int>(42);
std::weak_ptr<int> wptr = sptr;
// Check if expired
if (!wptr.expired()) {
// Convert to shared_ptr
if (auto locked = wptr.lock()) {
int value = *locked;
}
}
// Use count
long count = wptr.use_count();
// Reset
wptr.reset();
Raw Pointers
// Allocation
int* ptr = new int(42);
int* arr = new int[10];
// Deallocation
delete ptr;
delete[] arr;
// Null pointer (C++11)
int* ptr2 = nullptr;
// Check null
if (ptr2 == nullptr) {
// is null
}
Move Semantics
Rvalue References
// Lvalue reference
int x = 10;
int& lref = x;
// Rvalue reference (C++11)
int&& rref = 10;
int&& rref2 = std::move(x);
// Forward reference (universal reference)
template<typename T>
void func(T&& arg) {
// T can be lvalue or rvalue
}
Move Constructor
class MyClass {
public:
// Move constructor
MyClass(MyClass&& other) noexcept
: data(other.data) {
other.data = nullptr;
}
// Move assignment
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
private:
int* data;
};
std::move
#include <utility>
std::vector<int> v1 = {1, 2, 3};
// Move v1 into v2
std::vector<int> v2 = std::move(v1);
// v1 is now in valid but unspecified state
// Move into function
void func(std::vector<int> vec) {
// vec owns the data
}
func(std::move(v2));
Perfect Forwarding
#include <utility>
template<typename T>
void wrapper(T&& arg) {
// Forward arg preserving its value category
func(std::forward<T>(arg));
}
// Usage
int x = 10;
wrapper(x); // forwards as lvalue
wrapper(10); // forwards as rvalue
wrapper(std::move(x)); // forwards as rvalue
RAII Pattern
Basic RAII
// Resource Acquisition Is Initialization
class FileHandle {
public:
FileHandle(const std::string& filename) {
file = fopen(filename.c_str(), "r");
if (!file) {
throw std::runtime_error("Failed to open");
}
}
~FileHandle() {
if (file) {
fclose(file);
}
}
// Delete copy
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
private:
FILE* file;
};
// Usage
{
FileHandle handle("file.txt");
// Use file
} // Automatically closed
Lock Guard
#include <mutex>
std::mutex mtx;
void func() {
std::lock_guard<std::mutex> lock(mtx);
// Critical section
// Mutex automatically unlocked when lock goes out of scope
}
// Unique lock (more flexible)
void func2() {
std::unique_lock<std::mutex> lock(mtx);
// Can manually unlock
lock.unlock();
// Do something
lock.lock();
}
Scope Guard
// Custom scope guard
template<typename Func>
class ScopeGuard {
public:
explicit ScopeGuard(Func f)
: func(std::move(f)), active(true) {}
~ScopeGuard() {
if (active) func();
}
void dismiss() { active = false; }
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
private:
Func func;
bool active;
};
// Helper function
template<typename Func>
ScopeGuard<Func> makeScopeGuard(Func f) {
return ScopeGuard<Func>(std::move(f));
}
// Usage
void func() {
auto guard = makeScopeGuard([]() {
std::cout << "Cleanup\n";
});
// Cleanup happens automatically
}
Modern C++ Features
C++11 Features
// Auto type deduction
auto x = 42;
// Range-based for
for (const auto& item : container) {}
// Lambda expressions
auto lambda = [](int x) { return x * 2; };
// nullptr
int* ptr = nullptr;
// Move semantics
std::vector<int> v2 = std::move(v1);
// Smart pointers
auto ptr = std::make_unique<int>(42);
// Uniform initialization
std::vector<int> vec{1, 2, 3};
// Variadic templates
template<typename... Args>
void func(Args... args) {}
// Static assertions
static_assert(sizeof(int) == 4, "Size error");
C++14 Features
// Generic lambdas
auto lambda = [](auto x, auto y) {
return x + y;
};
// Return type deduction
auto add(int a, int b) {
return a + b;
}
// Binary literals
int x = 0b1010;
// Digit separators
int y = 1'000'000;
// std::make_unique
auto ptr = std::make_unique<int>(42);
// Variable templates
template<typename T>
constexpr T pi = T(3.1415926535897932385);
C++17 Features
// Structured bindings
auto [x, y] = std::make_pair(1, 2);
auto [key, value] = *map.find("key");
// If with initializer
if (auto it = map.find(key); it != map.end()) {}
// Fold expressions
template<typename... Args>
auto sum(Args... args) {
return (... + args);
}
// std::optional
std::optional<int> opt = 42;
if (opt.has_value()) {
int value = *opt;
}
// std::variant
std::variant<int, double, std::string> var;
var = 42;
var = "hello";
// std::any
std::any any = 42;
any = std::string("hello");
C++20 Features
// Concepts
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
template<Numeric T>
T add(T a, T b) { return a + b; }
// Ranges
#include <ranges>
auto even = [](int x) { return x % 2 == 0; };
auto result = vec
| std::views::filter(even)
| std::views::transform([](int x) { return x * 2; });
// Three-way comparison (spaceship)
auto operator<=>(const MyClass&) const = default;
// Coroutines
#include <coroutine>
generator<int> fibonacci() {
int a = 0, b = 1;
while (true) {
co_yield a;
auto next = a + b;
a = b;
b = next;
}
}
// Modules (experimental)
import std.core;
// consteval (compile-time only)
consteval int square(int x) {
return x * x;
}
C++23 Features
// std::expected
std::expected<int, std::string> divide(int a, int b) {
if (b == 0) {
return std::unexpected("Division by zero");
}
return a / b;
}
// std::print (formatted output)
std::print("Hello, {}!\n", "World");
std::println("Value: {}", 42);
// Multidimensional subscript operator
class Matrix {
auto operator[](int row, int col) const {
return data[row][col];
}
};
// if consteval
if consteval {
// Compile-time code
} else {
// Runtime code
}
// std::flat_map, std::flat_set
std::flat_map<int, std::string> map;
Common Idioms
Rule of Three
// If you define one, define all three:
// 1. Destructor
// 2. Copy constructor
// 3. Copy assignment operator
class MyClass {
public:
// Destructor
~MyClass() {
delete[] data;
}
// Copy constructor
MyClass(const MyClass& other)
: size(other.size) {
data = new int[size];
std::copy(other.data, other.data + size, data);
}
// Copy assignment
MyClass& operator=(const MyClass& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new int[size];
std::copy(other.data, other.data + size, data);
}
return *this;
}
private:
int* data;
size_t size;
};
Rule of Five
// C++11: Add move constructor and move assignment
class MyClass {
public:
~MyClass() { delete[] data; }
// Copy constructor
MyClass(const MyClass& other)
: size(other.size) {
data = new int[size];
std::copy(other.data, other.data + size, data);
}
// Copy assignment
MyClass& operator=(const MyClass& other) {
MyClass tmp(other);
std::swap(data, tmp.data);
std::swap(size, tmp.size);
return *this;
}
// Move constructor
MyClass(MyClass&& other) noexcept
: data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
// Move assignment
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
private:
int* data;
size_t size;
};
Rule of Zero
// Prefer using standard library types
// No need to define special member functions
class MyClass {
public:
// Compiler-generated functions are fine
// Use smart pointers and standard containers
private:
std::vector<int> data;
std::unique_ptr<Resource> resource;
std::string name;
};
Copy-and-Swap
class MyClass {
public:
// Copy constructor
MyClass(const MyClass& other)
: size(other.size) {
data = new int[size];
std::copy(other.data, other.data + size, data);
}
// Swap function
friend void swap(MyClass& first, MyClass& second) noexcept {
using std::swap;
swap(first.data, second.data);
swap(first.size, second.size);
}
// Copy assignment using copy-and-swap
MyClass& operator=(MyClass other) {
swap(*this, other);
return *this;
}
private:
int* data;
size_t size;
};
Compilation
GCC/G++
# Basic compilation
g++ main.cpp -o main
# C++ standard
g++ -std=c++20 main.cpp -o main
# Optimization levels
g++ -O0 main.cpp # No optimization
g++ -O1 main.cpp # Basic
g++ -O2 main.cpp # Recommended
g++ -O3 main.cpp # Aggressive
# Warnings
g++ -Wall -Wextra -Werror main.cpp
# Debug symbols
g++ -g main.cpp
# Include paths
g++ -I/path/to/headers main.cpp
# Link libraries
g++ main.cpp -lboost_system
# Multiple files
g++ file1.cpp file2.cpp -o program
Clang
# Basic compilation
clang++ main.cpp -o main
# C++ standard
clang++ -std=c++20 main.cpp -o main
# Optimization
clang++ -O2 main.cpp
# Warnings
clang++ -Wall -Wextra main.cpp
# Static analysis
clang++ --analyze main.cpp
# Address sanitizer
clang++ -fsanitize=address main.cpp
# Thread sanitizer
clang++ -fsanitize=thread main.cpp
CMake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(MyProject)
# C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Executable
add_executable(myapp main.cpp)
# Library
add_library(mylib lib.cpp)
# Link library
target_link_libraries(myapp mylib)
# Include directories
target_include_directories(myapp PRIVATE include)
# Build commands
mkdir build && cd build
cmake ..
cmake --build .
# Build type
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake -DCMAKE_BUILD_TYPE=Release ..
String Operations
std::string
#include <string>
// Declaration
std::string str = "Hello";
std::string str2("World");
// Concatenation
std::string result = str + " " + str2;
str += " World";
// Access
char c = str[0];
char c2 = str.at(1);
// Substring
std::string sub = str.substr(0, 5);
// Find
size_t pos = str.find("World");
if (pos != std::string::npos) {
// found
}
// Replace
str.replace(0, 5, "Hi");
// Size
size_t len = str.length();
size_t size = str.size();
// Comparison
if (str == "Hello") {}
int cmp = str.compare("World");
String Views (C++17)
#include <string_view>
// Non-owning string reference
std::string_view sv = "Hello World";
// Efficient substring (no copy)
std::string_view sub = sv.substr(0, 5);
// Works with std::string
std::string str = "Hello";
std::string_view sv2 = str;
// Caution: lifetime issues
std::string_view dangling() {
std::string temp = "Hello";
return temp; // Dangling reference!
}
String Conversion
#include <string>
// To string
std::string s1 = std::to_string(42);
std::string s2 = std::to_string(3.14);
// From string
int i = std::stoi("42");
long l = std::stol("1000000");
double d = std::stod("3.14");
// With error handling
size_t pos;
int x = std::stoi("42abc", &pos);
// pos is index of first invalid char
Exception Handling
Try-Catch
try {
// Code that may throw
throw std::runtime_error("Error occurred");
} catch (const std::runtime_error& e) {
std::cerr << "Runtime error: " << e.what() << '\n';
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << '\n';
} catch (...) {
std::cerr << "Unknown exception\n";
}
Custom Exceptions
class MyException : public std::exception {
public:
explicit MyException(const char* message)
: msg(message) {}
const char* what() const noexcept override {
return msg.c_str();
}
private:
std::string msg;
};
// Usage
throw MyException("Something went wrong");
Standard Exceptions
#include <stdexcept>
// Logic errors
throw std::logic_error("Logic error");
throw std::invalid_argument("Invalid arg");
throw std::domain_error("Domain error");
throw std::length_error("Length error");
throw std::out_of_range("Out of range");
// Runtime errors
throw std::runtime_error("Runtime error");
throw std::range_error("Range error");
throw std::overflow_error("Overflow");
throw std::underflow_error("Underflow");
RAII and Exceptions
void func() {
// RAII ensures cleanup on exception
std::unique_ptr<Resource> res =
std::make_unique<Resource>();
// May throw
riskyOperation();
// Resource automatically cleaned up
// even if exception is thrown
}
File I/O
Reading Files
#include <fstream>
#include <string>
// Read entire file
std::ifstream file("input.txt");
if (file.is_open()) {
std::string line;
while (std::getline(file, line)) {
// Process line
}
file.close();
}
// Read word by word
std::ifstream file2("input.txt");
std::string word;
while (file2 >> word) {
// Process word
}
// Read into string
std::ifstream file3("input.txt");
std::string content(
(std::istreambuf_iterator<char>(file3)),
std::istreambuf_iterator<char>()
);
Writing Files
#include <fstream>
// Write to file
std::ofstream file("output.txt");
if (file.is_open()) {
file << "Hello, World!" << '\n';
file << 42 << '\n';
file.close();
}
// Append to file
std::ofstream file2("output.txt", std::ios::app);
file2 << "Appended text\n";
// Binary mode
std::ofstream file3("output.bin", std::ios::binary);
int data[] = {1, 2, 3, 4, 5};
file3.write(reinterpret_cast<char*>(data), sizeof(data));
File Status
#include <fstream>
#include <filesystem>
// Check if file exists (C++17)
namespace fs = std::filesystem;
if (fs::exists("file.txt")) {
// exists
}
// File size
size_t size = fs::file_size("file.txt");
// Check if stream is open
std::ifstream file("input.txt");
if (!file.is_open()) {
std::cerr << "Failed to open file\n";
}
// Check for errors
if (file.fail()) {
// Error occurred
}
Also see
- C++ Reference - Comprehensive C++ reference
- Modern C++ Features - Guide to C++11/14/17/20/23
- C++ Core Guidelines - Best practices by Bjarne Stroustrup
- LearnCpp.com - Comprehensive C++ tutorial
- C++ Standard Draft - Latest C++ standard working draft