cpp-expert

安装量: 61
排名: #12300

安装

npx skills add https://github.com/personamanagmentlayer/pcl --skill cpp-expert

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 concept Numeric = std::integral || std::floating_point;

template concept Printable = requires(T t, std::ostream& os) { { os << t } -> std::same_as; };

// Use concepts template T add(T a, T b) { return a + b; }

template void print(const T& value) { std::cout << value << '\n'; }

// Concept with multiple requirements template concept Container = requires(T container) { typename T::value_type; { container.begin() } -> std::same_as; { container.end() } -> std::same_as; { container.size() } -> std::convertible_to; };

template void process(const C& container) { for (const auto& item : container) { std::cout << item << ' '; } }

Ranges and Views (C++20)

include

include

include

// Ranges std::vector numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 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> nested = {{1, 2}, {3, 4}, {5, 6}}; auto flattened = nested | std::views::join;

// 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 result(lazy.begin(), lazy.end()); // {12, 14, 16}

Coroutines (C++20)

include

include

include

// Generator coroutine template class Generator { public: struct promise_type { T current_value;

    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 handle; };

// Use generator Generator fibonacci() { int a = 0, b = 1; while (true) { co_yield a; auto next = a + b; a = b; b = next; } }

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 create_resource() { return std::make_unique(100); }

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 shared = std::make_shared(100); { std::shared_ptr shared2 = shared; // Reference count = 2 std::cout << "Use count: " << shared.use_count() << '\n'; // 2 } // shared2 destroyed, ref count = 1 // shared destroyed, Resource released

// weak_ptr - non-owning reference std::weak_ptr weak = shared; if (auto locked = weak.lock()) { // Use resource }

// Custom deleter auto file_deleter = { if (f) fclose(f); }; std::unique_ptr file( fopen("data.txt", "r"), file_deleter );

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 std::unique_ptr make_unique_custom(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); }

Templates and Metaprogramming

include

include

// Function template template T max(T a, T b) { return (a > b) ? a : b; }

// Class template template class Array { T data[N];

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 void print(Args... args) { ((std::cout << args << ' '), ...); // Fold expression (C++17) std::cout << '\n'; }

// SFINAE (Substitution Failure Is Not An Error) template typename std::enable_if::value, T>::type abs(T value) { return value < 0 ? -value : value; }

template typename std::enable_if::value, T>::type abs(T value) { return std::fabs(value); }

// Type traits template void check_type() { std::cout << std::boolalpha; std::cout << "is_integral: " << std::is_integral_v << '\n'; std::cout << "is_floating_point: " << std::is_floating_point_v << '\n'; std::cout << "is_pointer: " << std::is_pointer_v << '\n'; }

// 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 vec = {1, 2, 3, 4, 5}; vec.push_back(6); vec.emplace_back(7); // Construct in-place vec.reserve(100); // Pre-allocate capacity

// deque - double-ended queue std::deque deq = {1, 2, 3}; deq.push_front(0); deq.push_back(4);

// list - doubly-linked list std::list lst = {1, 2, 3}; lst.push_front(0); lst.push_back(4); lst.remove(2); // Remove all elements with value 2

// array - fixed-size array std::array arr = {1, 2, 3, 4, 5};

Associative Containers

include

include

include

include

// map - ordered key-value pairs std::map ages; ages["Alice"] = 30; ages["Bob"] = 25; ages.insert({"Charlie", 35});

// set - ordered unique elements std::set numbers = {3, 1, 4, 1, 5, 9}; numbers.insert(2);

// unordered_map - hash table std::unordered_map hash_map; hash_map["key"] = 42;

// unordered_set - hash set std::unordered_set hash_set = {1, 2, 3};

Algorithms

include

include

include

std::vector numbers = {5, 2, 8, 1, 9, 3, 7};

// 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 doubled(numbers.size()); std::transform(numbers.begin(), numbers.end(), doubled.begin(), { return n * 2; });

// Filtering std::vector evens; std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evens), { return n % 2 == 0; });

// 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 lock(mtx); ++shared_data; }

// Atomic std::atomic counter{0}; counter++; // Thread-safe counter.fetch_add(5);

// Future and promise std::promise prom; std::future fut = prom.get_future();

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( fopen("data.txt", "r"), &fclose ); // ... work with file // Automatically closed when leaving scope }

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/

返回排行榜