C++ Expert
Expert guidance for modern C++ development including C++20/23 features, STL, templates, memory management, and high-performance programming.
Core Concepts Modern C++ Features (C++20/23) Concepts and constraints Ranges and views Coroutines Modules Three-way comparison (spaceship operator) std::format std::span Designated initializers consteval and constinit Memory Management RAII (Resource Acquisition Is Initialization) Smart pointers (unique_ptr, shared_ptr, weak_ptr) Move semantics and perfect forwarding Memory allocation strategies Custom allocators Memory pools Performance Zero-cost abstractions Inline optimization Template metaprogramming Compile-time computation (constexpr) Cache-friendly data structures SIMD operations Modern C++ Syntax Concepts (C++20)
include
include
include
// Define concepts
template
template
// Use concepts
template
template
// Concept with multiple requirements
template
template
Ranges and Views (C++20)
include
include
include
// Ranges
std::vector
// Filter and transform with views auto even_squares = numbers | std::views::filter( { return n % 2 == 0; }) | std::views::transform( { return n * n; });
for (int value : even_squares) { std::cout << value << ' '; // 4 16 36 64 100 }
// Take first N elements auto first_three = numbers | std::views::take(3);
// Drop first N elements auto skip_two = numbers | std::views::drop(2);
// Reverse auto reversed = numbers | std::views::reverse;
// Join multiple ranges
std::vector
// Split string std::string text = "one,two,three"; auto words = text | std::views::split(',');
// Lazy evaluation - nothing computed yet auto lazy = numbers | std::views::filter( { return n > 5; }) | std::views::transform( { return n * 2; }) | std::views::take(3);
// Computation happens here
std::vector
Coroutines (C++20)
include
include
include
// Generator coroutine
template
auto get_return_object() {
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
}
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
auto yield_value(T value) {
current_value = value;
return std::suspend_always{};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
explicit Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
~Generator() { if (handle) handle.destroy(); }
bool next() {
handle.resume();
return !handle.done();
}
T value() const {
return handle.promise().current_value;
}
private:
std::coroutine_handle
// Use generator
Generator
int main() { auto fib = fibonacci(); for (int i = 0; i < 10; ++i) { fib.next(); std::cout << fib.value() << ' '; // 0 1 1 2 3 5 8 13 21 34 } }
Smart Pointers
include
include
class Resource { int* data; public: Resource(int size) : data(new int[size]) { std::cout << "Resource acquired\n"; }
~Resource() {
delete[] data;
std::cout << "Resource released\n";
}
};
// unique_ptr - exclusive ownership
std::unique_ptr
auto resource = create_resource(); // resource.reset(); // Manually release // auto copy = resource; // Error: cannot copy unique_ptr auto moved = std::move(resource); // Transfer ownership
// shared_ptr - shared ownership
std::shared_ptr
// weak_ptr - non-owning reference
std::weak_ptr
// Custom deleter
auto file_deleter = { if (f) fclose(f); };
std::unique_ptr
Move Semantics
include
include
class Buffer { int* data; size_t size;
public: // Constructor Buffer(size_t s) : size(s), data(new int[s]) { std::cout << "Constructor\n"; }
// Destructor
~Buffer() {
delete[] data;
std::cout << "Destructor\n";
}
// Copy constructor
Buffer(const Buffer& other) : size(other.size), data(new int[other.size]) {
std::copy(other.data, other.data + size, data);
std::cout << "Copy constructor\n";
}
// Move constructor
Buffer(Buffer&& other) noexcept : size(other.size), data(other.data) {
other.data = nullptr;
other.size = 0;
std::cout << "Move constructor\n";
}
// Copy assignment
Buffer& operator=(const Buffer& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new int[size];
std::copy(other.data, other.data + size, data);
std::cout << "Copy assignment\n";
}
return *this;
}
// Move assignment
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
std::cout << "Move assignment\n";
}
return *this;
}
};
// Perfect forwarding
template
Templates and Metaprogramming
include
include
// Function template
template
// Class template
template
public: constexpr size_t size() const { return N; }
T& operator[](size_t index) { return data[index]; }
const T& operator[](size_t index) const { return data[index]; }
};
// Variadic templates
template
// SFINAE (Substitution Failure Is Not An Error)
template
template
// Type traits
template
// Compile-time computation constexpr int factorial(int n) { return n <= 1 ? 1 : n * factorial(n - 1); }
constexpr int fact10 = factorial(10); // Computed at compile time
std::format (C++20)
include
include
int main() { int age = 30; std::string name = "Alice";
// Basic formatting
std::cout << std::format("Hello, {}!", name) << '\n';
// Positional arguments
std::cout << std::format("{1} is {0} years old", age, name) << '\n';
// Format specifiers
double pi = 3.14159265359;
std::cout << std::format("Pi: {:.2f}", pi) << '\n'; // 3.14
// Width and alignment
std::cout << std::format("{:<10} {:>10}", "left", "right") << '\n';
// Numbers
int num = 42;
std::cout << std::format("Dec: {0:d}, Hex: {0:x}, Bin: {0:b}", num) << '\n';
// Padding
std::cout << std::format("{:0>5}", num) << '\n'; // 00042
return 0;
}
STL Containers Sequential Containers
include
include
include
include
// vector - dynamic array
std::vector
// deque - double-ended queue
std::deque
// list - doubly-linked list
std::list
// array - fixed-size array
std::array
Associative Containers
include
include
include
include
// map - ordered key-value pairs
std::map
// set - ordered unique elements
std::set
// unordered_map - hash table
std::unordered_map
// unordered_set - hash set
std::unordered_set
Algorithms
include
include
include
std::vector
// Sorting
std::sort(numbers.begin(), numbers.end());
std::sort(numbers.begin(), numbers.end(), std::greater
// Searching auto it = std::find(numbers.begin(), numbers.end(), 8); bool found = std::binary_search(numbers.begin(), numbers.end(), 5);
// Transforming
std::vector
// Filtering
std::vector
// Accumulate
int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
int product = std::accumulate(numbers.begin(), numbers.end(), 1,
std::multiplies
// Partition auto pivot = std::partition(numbers.begin(), numbers.end(), { return n < 5; });
// Remove numbers.erase(std::remove(numbers.begin(), numbers.end(), 5), numbers.end());
// Unique (remove consecutive duplicates) std::sort(numbers.begin(), numbers.end()); numbers.erase(std::unique(numbers.begin(), numbers.end()), numbers.end());
Concurrency
include
include
include
include
// Thread void worker(int id) { std::cout << "Thread " << id << '\n'; }
std::thread t1(worker, 1); std::thread t2(worker, 2); t1.join(); t2.join();
// Mutex std::mutex mtx; int shared_data = 0;
void increment() {
std::lock_guard
// Atomic
std::atomic
// Future and promise
std::promise
std::thread t(&prom { std::this_thread::sleep_for(std::chrono::seconds(1)); prom.set_value(42); });
int result = fut.get(); // Blocks until ready t.join();
// async auto future = std::async(std::launch::async, { return 42; });
int value = future.get();
Build Systems CMake
CMakeLists.txt
cmake_minimum_required(VERSION 3.20) project(MyApp VERSION 1.0.0 LANGUAGES CXX)
Set C++ standard
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON)
Compiler flags
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") add_compile_options(-Wall -Wextra -Wpedantic -O3) endif()
Find packages
find_package(Threads REQUIRED) find_package(Boost 1.75 REQUIRED COMPONENTS system filesystem)
Add executable
add_executable(myapp src/main.cpp src/module.cpp include/module.h )
Include directories
target_include_directories(myapp PRIVATE include)
Link libraries
target_link_libraries(myapp PRIVATE Threads::Threads Boost::system Boost::filesystem )
Install
install(TARGETS myapp DESTINATION bin)
Best Practices RAII // ❌ Bad: Manual resource management void process_file() { FILE* f = fopen("data.txt", "r"); // ... work with file fclose(f); // Easy to forget }
// ✅ Good: RAII with smart pointers
void process_file() {
auto file = std::unique_ptr
Const Correctness class Data { int value;
public: // Const method int get_value() const { return value; }
// Non-const method
void set_value(int v) { value = v; }
};
// Const reference parameter void process(const Data& data) { int v = data.get_value(); // OK // data.set_value(42); // Error: cannot modify const object }
Rule of Zero/Three/Five Rule of Zero: If you don't manage resources, don't declare special members Rule of Three: If you declare destructor, copy constructor, or copy assignment, declare all three Rule of Five: Add move constructor and move assignment Anti-Patterns to Avoid
❌ Raw pointers for ownership: Use smart pointers ❌ Manual memory management: Use RAII ❌ Using C-style arrays: Use std::array or std::vector ❌ Ignoring const correctness: Mark everything const that can be ❌ Unnecessary copies: Use move semantics and references ❌ Premature optimization: Profile before optimizing ❌ Using new without delete: Use smart pointers
Resources C++ Reference: https://en.cppreference.com/ C++ Core Guidelines: https://isocpp.github.io/CppCoreGuidelines/ Compiler Explorer: https://godbolt.org/ CPP Reference: https://cplusplus.com/