diff --git a/cpp23_features_demo/README.md b/cpp23_features_demo/README.md new file mode 100644 index 00000000..6d07d21a --- /dev/null +++ b/cpp23_features_demo/README.md @@ -0,0 +1,41 @@ +# C++23 Features Demo + +This directory contains examples of new features introduced in C++23. + +## C++23 New Features + +C++23 is the latest standard of the C++ programming language, released in 2023. It introduces several new features and improvements, including: + +1. **std::expected** - A type for representing either a value or an error +2. **std::mdspan** - A multi-dimensional span +3. **Module system enhancements** - Improved support for modules +4. **std::format** improvements - More formatting options +5. **std::ranges improvements** - New range adapters and algorithms +6. **Coroutine improvements** - Better support for coroutines +7. **And more...** + +## Contents + +1. **std_expected.cpp** - Example of using std::expected for error handling +2. **std_mdspan.cpp** - Example of using std::mdspan for multi-dimensional arrays +3. **modules_demo.cpp** - Example of using C++23 modules +4. **format_improvements.cpp** - Example of C++23 format improvements +5. **ranges_improvements.cpp** - Example of C++23 ranges improvements + +## Build and Run + +To build and run these examples, you need a C++23 compliant compiler (e.g., GCC 13+, Clang 16+, MSVC 2022+). + +```bash +# Build with GCC +g++ -std=c++23 std_expected.cpp -o std_expected +./std_expected + +# Build with Clang +clang++ -std=c++23 std_expected.cpp -o std_expected +./std_expected + +# Build with MSVC +cl /std:c++23 std_expected.cpp +std_expected.exe +``` \ No newline at end of file diff --git a/cpp23_features_demo/modules_demo.cpp b/cpp23_features_demo/modules_demo.cpp new file mode 100644 index 00000000..fb341d3c --- /dev/null +++ b/cpp23_features_demo/modules_demo.cpp @@ -0,0 +1,40 @@ +// 模块接口单元:module_demo +// 模块声明 +module module_demo; + +// 导出公共接口 +#include +#include + +export namespace module_demo { + // 公共函数声明 + void hello(); + std::string get_message(); +} + +// 模块实现单元 +module module_demo; + +// 导入必要的头文件 +#include +#include + +// 实现公共函数 +namespace module_demo { + void hello() { + std::cout << "Hello from module_demo!" << std::endl; + } + + std::string get_message() { + return "This is a message from module_demo."; + } +} + +// 主程序 +import module_demo; + +int main() { + module_demo::hello(); + std::cout << module_demo::get_message() << std::endl; + return 0; +} diff --git a/cpp23_features_demo/std_expected.cpp b/cpp23_features_demo/std_expected.cpp new file mode 100644 index 00000000..249c7af0 --- /dev/null +++ b/cpp23_features_demo/std_expected.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include + +// 尝试将字符串转换为整数,返回std::expected +std::expected string_to_int(const std::string& str) { + std::istringstream iss(str); + int value; + if (iss >> value) { + return value; // 成功,返回值 + } else { + return std::unexpected("Failed to convert string to int: " + str); // 失败,返回错误 + } +} + +int main() { + // 测试成功的情况 + std::string valid_str = "123"; + auto result1 = string_to_int(valid_str); + if (result1) { + std::cout << "Successfully converted \"" << valid_str << "\" to " << *result1 << std::endl; + } else { + std::cout << "Error: " << result1.error() << std::endl; + } + + // 测试失败的情况 + std::string invalid_str = "abc"; + auto result2 = string_to_int(invalid_str); + if (result2) { + std::cout << "Successfully converted \"" << invalid_str << "\" to " << *result2 << std::endl; + } else { + std::cout << "Error: " << result2.error() << std::endl; + } + + // 使用value()方法获取值,如果失败则抛出异常 + try { + int value = result1.value(); + std::cout << "Value from value(): " << value << std::endl; + } catch (const std::bad_expected_access& e) { + std::cout << "Exception: " << e.what() << std::endl; + } + + // 使用or_else()方法处理错误 + result2.or_else([](std::string error) { + std::cout << "or_else() error: " << error << std::endl; + return std::expected(std::unexpected(error)); + }); + + // 使用transform()方法转换值 + auto result3 = result1.transform([](int value) { + return value * 2; + }); + if (result3) { + std::cout << "Transformed value: " << *result3 << std::endl; + } + + return 0; +} diff --git a/cpp23_features_demo/std_mdspan.cpp b/cpp23_features_demo/std_mdspan.cpp new file mode 100644 index 00000000..db7cad7b --- /dev/null +++ b/cpp23_features_demo/std_mdspan.cpp @@ -0,0 +1,76 @@ +#include +#include +#include + +// 打印多维数组 +void print_mdspan(std::mdspan m) { + for (std::size_t i = 0; i < m.extent(0); ++i) { + for (std::size_t j = 0; j < m.extent(1); ++j) { + std::cout << m[i][j] << " "; + } + std::cout << std::endl; + } +} + +// 矩阵乘法 +std::vector matrix_multiply( + std::mdspan a, + std::mdspan b) { + if (a.extent(1) != b.extent(0)) { + throw std::invalid_argument("Matrix dimensions mismatch"); + } + + std::size_t rows = a.extent(0); + std::size_t cols = b.extent(1); + std::size_t common = a.extent(1); + std::vector result(rows * cols); + std::mdspan res(result.data(), rows, cols); + + for (std::size_t i = 0; i < rows; ++i) { + for (std::size_t j = 0; j < cols; ++j) { + int sum = 0; + for (std::size_t k = 0; k < common; ++k) { + sum += a[i][k] * b[k][j]; + } + res[i][j] = sum; + } + } + + return result; +} + +int main() { + // 创建一个3x3的二维数组 + std::vector data = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::mdspan m(data.data(), 3, 3); + + // 访问和修改元素 + std::cout << "Original matrix:" << std::endl; + print_mdspan(m); + + m[1][1] = 10; // 修改中间元素 + std::cout << "Matrix after modification:" << std::endl; + print_mdspan(m); + + // 创建一个3x2的二维数组 + std::vector data2 = {1, 2, 3, 4, 5, 6}; + std::mdspan m2(data2.data(), 3, 2); + + // 矩阵乘法 + std::cout << "Matrix multiplication:" << std::endl; + std::cout << "Matrix A:" << std::endl; + print_mdspan(m); + std::cout << "Matrix B:" << std::endl; + print_mdspan(m2); + + try { + std::vector result = matrix_multiply(m, m2); + std::mdspan res(result.data(), 3, 2); + std::cout << "Result:" << std::endl; + print_mdspan(res); + } catch (const std::invalid_argument& e) { + std::cout << "Error: " << e.what() << std::endl; + } + + return 0; +} diff --git a/cpp_memory_management/README.md b/cpp_memory_management/README.md new file mode 100644 index 00000000..bf5c4f6b --- /dev/null +++ b/cpp_memory_management/README.md @@ -0,0 +1,44 @@ +# C++内存管理最佳实践 + +本目录包含C++内存管理的最佳实践示例,包括智能指针的正确使用和内存泄漏的避免方法。 + +## 内存管理简介 + +C++是一种静态类型的编程语言,它允许程序员直接管理内存。这为程序员提供了很大的灵活性,但也带来了内存泄漏、野指针和悬垂指针等问题。 + +为了避免这些问题,C++11引入了智能指针,它们是一种自动管理内存的工具,可以在对象不再被使用时自动释放内存。 + +## 目录内容 + +1. **smart_pointers.cpp** - 智能指针的正确使用示例 +2. **memory_leaks.cpp** - 内存泄漏的避免方法 +3. **unique_ptr_example.cpp** - unique_ptr的使用示例 +4. **shared_ptr_example.cpp** - shared_ptr的使用示例 +5. **weak_ptr_example.cpp** - weak_ptr的使用示例 + +## 构建和运行 + +要构建和运行这些示例,您需要一个C++编译器(例如GCC、Clang、MSVC)。 + +```bash +# 使用GCC构建 +g++ -std=c++17 smart_pointers.cpp -o smart_pointers +./smart_pointers + +# 使用Clang构建 +clang++ -std=c++17 smart_pointers.cpp -o smart_pointers +./smart_pointers + +# 使用MSVC构建 +cl /std:c++17 smart_pointers.cpp +smart_pointers.exe +``` + +## 内存管理最佳实践 + +1. **使用智能指针**:优先使用unique_ptr、shared_ptr和weak_ptr等智能指针,而不是手动管理内存。 +2. **避免裸指针**:尽量避免使用裸指针,除非您确实需要直接管理内存。 +3. **避免内存泄漏**:确保每个new操作都有对应的delete操作,或者使用智能指针自动管理内存。 +4. **避免悬垂指针**:确保指针指向的内存不会被提前释放。 +5. **使用RAII**:使用资源获取即初始化(RAII)技术来管理资源,例如内存、文件句柄等。 +6. **避免循环引用**:使用weak_ptr来避免shared_ptr之间的循环引用。 \ No newline at end of file diff --git a/cpp_memory_management/memory_leaks.cpp b/cpp_memory_management/memory_leaks.cpp new file mode 100644 index 00000000..204b92fb --- /dev/null +++ b/cpp_memory_management/memory_leaks.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +// 内存泄漏示例1:忘记释放动态分配的内存 +void memory_leak_example1() { + std::cout << "\n--- Memory Leak Example 1 ---" << std::endl; + int* ptr = new int(42); + std::cout << "Value of ptr: " << *ptr << std::endl; + // 忘记释放ptr指向的内存 + // delete ptr; + std::cout << "Memory leak occurred: ptr is not deleted." << std::endl; +} + +// 内存泄漏示例2:在异常情况下未释放内存 +void memory_leak_example2() { + std::cout << "\n--- Memory Leak Example 2 ---" << std::endl; + int* ptr = new int(42); + try { + std::cout << "Value of ptr: " << *ptr << std::endl; + throw std::runtime_error("An exception occurred."); + // 异常发生后,以下代码不会执行 + delete ptr; + } catch (const std::exception& e) { + std::cout << "Exception caught: " << e.what() << std::endl; + std::cout << "Memory leak occurred: ptr is not deleted in exception handler." << std::endl; + } + // 如果没有在catch块中释放内存,就会发生内存泄漏 +} + +// 内存泄漏示例3:循环引用 +class Node { +public: + std::shared_ptr next; + std::string data; + + Node(const std::string& data) : data(data) { + std::cout << "Node constructor called: " << data << std::endl; + } + + ~Node() { + std::cout << "Node destructor called: " << data << std::endl; + } +}; + +void memory_leak_example3() { + std::cout << "\n--- Memory Leak Example 3 ---" << std::endl; + std::shared_ptr node1 = std::make_shared("Node 1"); + std::shared_ptr node2 = std::make_shared("Node 2"); + node1->next = node2; + node2->next = node1; // 循环引用 + std::cout << "Node 1 reference count: " << node1.use_count() << std::endl; + std::cout << "Node 2 reference count: " << node2.use_count() << std::endl; + // 当node1和node2离开作用域时,它们的引用计数都是2,不会被销毁 + std::cout << "Memory leak occurred: nodes are not deleted due to circular reference." << std::endl; +} + +// 避免内存泄漏示例:使用智能指针 +void avoid_memory_leak_example() { + std::cout << "\n--- Avoid Memory Leak Example ---" << std::endl; + // 使用unique_ptr避免内存泄漏 + std::unique_ptr ptr = std::make_unique(42); + std::cout << "Value of ptr: " << *ptr << std::endl; + // 不需要手动释放内存,unique_ptr会自动释放 + + // 使用shared_ptr避免异常情况下的内存泄漏 + std::shared_ptr ptr2 = std::make_shared(100); + try { + std::cout << "Value of ptr2: " << *ptr2 << std::endl; + throw std::runtime_error("An exception occurred."); + } catch (const std::exception& e) { + std::cout << "Exception caught: " << e.what() << std::endl; + // ptr2会自动释放内存,不会发生内存泄漏 + } + + // 使用weak_ptr避免循环引用 + class Node2 { + public: + std::weak_ptr next; + std::string data; + + Node2(const std::string& data) : data(data) { + std::cout << "Node2 constructor called: " << data << std::endl; + } + + ~Node2() { + std::cout << "Node2 destructor called: " << data << std::endl; + } + }; + + std::shared_ptr node3 = std::make_shared("Node 3"); + std::shared_ptr node4 = std::make_shared("Node 4"); + node3->next = node4; + node4->next = node3; // 使用weak_ptr不会导致循环引用 + std::cout << "Node 3 reference count: " << node3.use_count() << std::endl; + std::cout << "Node 4 reference count: " << node4.use_count() << std::endl; + // 当node3和node4离开作用域时,它们的引用计数都是1,会被销毁 +} + +int main() { + memory_leak_example1(); + memory_leak_example2(); + memory_leak_example3(); + avoid_memory_leak_example(); + + std::cout << "\n--- End of Program ---" << std::endl; + return 0; +} diff --git a/cpp_memory_management/smart_pointers.cpp b/cpp_memory_management/smart_pointers.cpp new file mode 100644 index 00000000..6c6a6fa7 --- /dev/null +++ b/cpp_memory_management/smart_pointers.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +class Person { +public: + std::string name; + int age; + + Person(const std::string& name, int age) : name(name), age(age) { + std::cout << "Person constructor called: " << name << std::endl; + } + + ~Person() { + std::cout << "Person destructor called: " << name << std::endl; + } + + void greet() const { + std::cout << "Hello, my name is " << name << " and I'm " << age << " years old." << std::endl; + } +}; + +std::unique_ptr unique_ptr_example() { + std::cout << "\n--- unique_ptr Example ---" << std::endl; + std::unique_ptr alice = std::make_unique("Alice", 30); + alice->greet(); + std::cout << "unique_ptr alice owns the object: " << (alice != nullptr) << std::endl; + + std::unique_ptr bob = std::move(alice); + bob->greet(); + std::cout << "unique_ptr alice owns the object: " << (alice != nullptr) << std::endl; + std::cout << "unique_ptr bob owns the object: " << (bob != nullptr) << std::endl; + + return bob; +} + +void shared_ptr_example() { + std::cout << "\n--- shared_ptr Example ---" << std::endl; + std::shared_ptr charlie = std::make_shared("Charlie", 25); + std::cout << "Reference count: " << charlie.use_count() << std::endl; + + { + std::shared_ptr dave = charlie; + std::cout << "Reference count: " << charlie.use_count() << std::endl; + dave->greet(); + } + + std::cout << "Reference count after dave goes out of scope: " << charlie.use_count() << std::endl; + charlie->greet(); +} + +void weak_ptr_example() { + std::cout << "\n--- weak_ptr Example ---" << std::endl; + std::shared_ptr eve = std::make_shared("Eve", 35); + std::weak_ptr weak_eve = eve; + std::cout << "Reference count: " << eve.use_count() << std::endl; + std::cout << "weak_ptr is expired: " << weak_eve.expired() << std::endl; + + if (auto shared_eve = weak_eve.lock()) { + shared_eve->greet(); + std::cout << "Reference count after locking weak_ptr: " << eve.use_count() << std::endl; + } + + eve.reset(); + std::cout << "weak_ptr is expired: " << weak_eve.expired() << std::endl; + + if (auto shared_eve = weak_eve.lock()) { + shared_eve->greet(); + } else { + std::cout << "weak_ptr points to an expired object." << std::endl; + } +} + +int main() { + auto bob = unique_ptr_example(); + shared_ptr_example(); + weak_ptr_example(); + + std::cout << "\n--- End of Program ---" << std::endl; + // bob will be destroyed here, calling the destructor of Person + return 0; +} diff --git a/cross_platform_examples/README.md b/cross_platform_examples/README.md new file mode 100644 index 00000000..8f1cfe35 --- /dev/null +++ b/cross_platform_examples/README.md @@ -0,0 +1,64 @@ +# 跨平台代码示例 + +本目录包含跨平台C++代码示例,展示如何使用条件编译和跨平台库编写可在Windows、Linux和macOS上运行的代码。 + +## 跨平台开发简介 + +跨平台开发是指编写可在多个操作系统上运行的代码。为了实现这一点,开发人员需要使用跨平台库和条件编译来处理不同操作系统之间的差异。 + +### 条件编译 + +条件编译是一种在编译时根据预定义的宏来选择不同代码路径的技术。例如,可以使用以下预定义宏来检测操作系统: + +- `_WIN32`:Windows +- `__linux__`:Linux +- `__APPLE__`:macOS + +### 跨平台库 + +跨平台库是一种提供统一接口的库,可以在多个操作系统上运行。例如,Boost库和Qt库都是跨平台库。 + +## 目录内容 + +1. **file_system.cpp** - 跨平台文件系统操作示例 +2. **thread_example.cpp** - 跨平台线程操作示例 +3. **networking.cpp** - 跨平台网络操作示例 + +## 构建和运行 + +要构建和运行这些示例,您需要一个C++编译器(例如GCC、Clang、MSVC)。 + +### Windows + +使用MSVC构建: + +```bash +cl /std:c++17 file_system.cpp +file_system.exe +``` + +### Linux + +使用GCC构建: + +```bash +g++ -std=c++17 file_system.cpp -o file_system +./file_system +``` + +### macOS + +使用Clang构建: + +```bash +clang++ -std=c++17 file_system.cpp -o file_system +./file_system +``` + +## 跨平台开发最佳实践 + +1. **使用跨平台库**:优先使用跨平台库,而不是直接调用操作系统API。 +2. **使用条件编译**:使用条件编译来处理不同操作系统之间的差异。 +3. **避免使用平台特定的API**:尽量避免使用平台特定的API,除非您确实需要。 +4. **测试多个平台**:确保您的代码在所有目标平台上都能正常运行。 +5. **使用CMake**:使用CMake来管理跨平台构建。 \ No newline at end of file diff --git a/cross_platform_examples/file_system.cpp b/cross_platform_examples/file_system.cpp new file mode 100644 index 00000000..8770210d --- /dev/null +++ b/cross_platform_examples/file_system.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +namespace fs = std::filesystem; + +// 打印文件信息 +void print_file_info(const fs::path& path) { + if (fs::exists(path)) { + std::cout << "Path: " << path << std::endl; + std::cout << "Is directory: " << fs::is_directory(path) << std::endl; + std::cout << "Is regular file: " << fs::is_regular_file(path) << std::endl; + if (fs::is_regular_file(path)) { + std::cout << "File size: " << fs::file_size(path) << " bytes" << std::endl; + } + std::cout << "Last write time: " << fs::last_write_time(path).time_since_epoch().count() << std::endl; + } else { + std::cout << "Path does not exist: " << path << std::endl; + } +} + +// 遍历目录 +void traverse_directory(const fs::path& path) { + if (!fs::exists(path) || !fs::is_directory(path)) { + std::cout << "Path is not a directory: " << path << std::endl; + return; + } + + std::cout << "Directory contents: " << path << std::endl; + for (const auto& entry : fs::directory_iterator(path)) { + std::cout << " " << entry.path().filename(); + if (fs::is_directory(entry.path())) { + std::cout << "/"; + } + std::cout << std::endl; + } +} + +// 创建目录 +void create_directory(const fs::path& path) { + try { + if (fs::create_directory(path)) { + std::cout << "Directory created: " << path << std::endl; + } else { + std::cout << "Directory already exists: " << path << std::endl; + } + } catch (const std::exception& e) { + std::cout << "Error creating directory: " << e.what() << std::endl; + } +} + +// 创建文件 +void create_file(const fs::path& path, const std::string& content) { + try { + std::ofstream file(path); + if (file.is_open()) { + file << content; + file.close(); + std::cout << "File created: " << path << std::endl; + } else { + std::cout << "Error creating file: " << path << std::endl; + } + } catch (const std::exception& e) { + std::cout << "Error creating file: " << e.what() << std::endl; + } +} + +int main() { + std::cout << "--- Cross-platform File System Example ---" << std::endl; + + // 平台特定路径 + fs::path current_path = fs::current_path(); + std::cout << "Current path: " << current_path << std::endl; + + // 测试文件路径操作 + fs::path test_path = current_path / "test_directory" / "test_file.txt"; + std::cout << "Test path: " << test_path << std::endl; + std::cout << "Parent path: " << test_path.parent_path() << std::endl; + std::cout << "Filename: " << test_path.filename() << std::endl; + std::cout << "Extension: " << test_path.extension() << std::endl; + + // 创建目录 + create_directory(test_path.parent_path()); + + // 创建文件 + create_file(test_path, "Hello, cross-platform file system!"); + + // 打印文件信息 + print_file_info(test_path); + + // 遍历目录 + traverse_directory(test_path.parent_path()); + + // 删除文件和目录 + try { + fs::remove(test_path); + std::cout << "File deleted: " << test_path << std::endl; + fs::remove(test_path.parent_path()); + std::cout << "Directory deleted: " << test_path.parent_path() << std::endl; + } catch (const std::exception& e) { + std::cout << "Error deleting file or directory: " << e.what() << std::endl; + } + + return 0; +} diff --git a/modern_cpp_coroutine/README.md b/modern_cpp_coroutine/README.md new file mode 100644 index 00000000..d217e552 --- /dev/null +++ b/modern_cpp_coroutine/README.md @@ -0,0 +1,31 @@ +# Modern C++ Coroutine + +This directory contains examples and implementations of C++20 coroutine features. + +## What is Coroutine? + +Coroutines are a new feature in C++20 that allow functions to be suspended and resumed later, providing a more natural way to write asynchronous code. + +## Contents + +1. **basic_coroutine.cpp** - Basic coroutine examples +2. **task_scheduler.cpp** - Task scheduling with coroutines +3. **async_io.cpp** - Asynchronous IO using coroutines + +## Build and Run + +To build and run these examples, you need a C++20 compliant compiler (e.g., GCC 10+, Clang 10+, MSVC 2019+). + +```bash +# Build with GCC +g++ -std=c++20 basic_coroutine.cpp -o basic_coroutine +./basic_coroutine + +# Build with Clang +clang++ -std=c++20 basic_coroutine.cpp -o basic_coroutine +./basic_coroutine + +# Build with MSVC +cl /std:c++20 basic_coroutine.cpp +basic_coroutine.exe +``` \ No newline at end of file diff --git a/modern_cpp_coroutine/async_io.cpp b/modern_cpp_coroutine/async_io.cpp new file mode 100644 index 00000000..a67f6e74 --- /dev/null +++ b/modern_cpp_coroutine/async_io.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace asio = boost::asio; +using boost::system::error_code; + +// 自定义task类型,用于封装协程的状态和结果 +template +struct task { + // promise_type是协程的核心,负责协程的初始化、挂起和恢复 + struct promise_type { + T value; + std::exception_ptr exception; + std::coroutine_handle handle; + + // 获取协程的返回对象 + task get_return_object() { + handle = std::coroutine_handle::from_promise(*this); + return task(handle); + } + + // 初始挂起状态,返回std::suspend_always表示协程创建后立即挂起 + std::suspend_always initial_suspend() { + return {}; + } + + // 最终挂起状态,返回std::suspend_always表示协程完成后挂起 + std::suspend_always final_suspend() noexcept { + return {}; + } + + // 处理协程的返回值 + void return_value(T v) { + value = std::move(v); + } + + // 处理协程中的异常 + void unhandled_exception() { + exception = std::current_exception(); + } + }; + + std::coroutine_handle handle; + + // 构造函数 + explicit task(std::coroutine_handle h) : handle(h) {} + + // 析构函数,确保协程被正确销毁 + ~task() { + if (handle) { + handle.destroy(); + } + } + + // 禁止拷贝构造和拷贝赋值 + task(const task&) = delete; + task& operator=(const task&) = delete; + + // 允许移动构造和移动赋值 + task(task&& other) noexcept : handle(other.handle) { + other.handle = nullptr; + } + + task& operator=(task&& other) noexcept { + if (this != &other) { + if (handle) { + handle.destroy(); + } + handle = other.handle; + other.handle = nullptr; + } + return *this; + } + + // 恢复协程执行 + bool resume() { + if (!handle || handle.done()) { + return false; + } + handle.resume(); + return !handle.done(); + } + + // 获取协程的结果 + T get_result() { + if (handle && handle.done()) { + if (handle.promise().exception) { + std::rethrow_exception(handle.promise().exception); + } + return std::move(handle.promise().value); + } + throw std::runtime_error("Coroutine not completed"); + } +}; + +// 异步读取文件的协程函数 +asio::awaitable async_read_file(const std::string& filename) { + asio::io_context io_context; + asio::steady_timer timer(io_context, std::chrono::seconds(1)); + + // 模拟异步IO操作,等待1秒 + co_await timer.async_wait(asio::use_awaitable); + + // 打开文件并读取内容 + std::ifstream file(filename); + if (!file.is_open()) { + co_return "Failed to open file: " + filename; + } + + std::string content; + std::string line; + while (std::getline(file, line)) { + content += line + "\n"; + } + + co_return content; +} + +int main() { + try { + asio::io_context io_context; + asio::co_spawn(io_context, async_read_file("test.txt"), [](std::exception_ptr e, std::string result) { + if (e) { + std::rethrow_exception(e); + } + std::cout << "File content: " << result << std::endl; + }); + + io_context.run(); + } catch (const std::exception& e) { + std::cerr << "Exception: " << e.what() << std::endl; + } + + return 0; +} diff --git a/modern_cpp_coroutine/basic_coroutine.cpp b/modern_cpp_coroutine/basic_coroutine.cpp new file mode 100644 index 00000000..e4042788 --- /dev/null +++ b/modern_cpp_coroutine/basic_coroutine.cpp @@ -0,0 +1,109 @@ +#include +#include +#include + +// 自定义task类型,用于封装协程的状态和结果 +template +struct task { + // promise_type是协程的核心,负责协程的初始化、挂起和恢复 + struct promise_type { + T value; + std::exception_ptr exception; + + // 获取协程的返回对象 + task get_return_object() { + return task(std::coroutine_handle::from_promise(*this)); + } + + // 初始挂起状态,返回std::suspend_always表示协程创建后立即挂起 + std::suspend_always initial_suspend() { + return {}; + } + + // 最终挂起状态,返回std::suspend_always表示协程完成后挂起 + std::suspend_always final_suspend() noexcept { + return {}; + } + + // 处理协程的返回值 + void return_value(T v) { + value = std::move(v); + } + + // 处理协程中的异常 + void unhandled_exception() { + exception = std::current_exception(); + } + }; + + std::coroutine_handle handle; + + // 构造函数 + explicit task(std::coroutine_handle h) : handle(h) {} + + // 析构函数,确保协程被正确销毁 + ~task() { + if (handle) { + handle.destroy(); + } + } + + // 禁止拷贝构造和拷贝赋值 + task(const task&) = delete; + task& operator=(const task&) = delete; + + // 允许移动构造和移动赋值 + task(task&& other) noexcept : handle(other.handle) { + other.handle = nullptr; + } + + task& operator=(task&& other) noexcept { + if (this != &other) { + if (handle) { + handle.destroy(); + } + handle = other.handle; + other.handle = nullptr; + } + return *this; + } + + // 恢复协程执行 + bool resume() { + if (!handle || handle.done()) { + return false; + } + handle.resume(); + return !handle.done(); + } + + // 获取协程的结果 + T get_result() { + if (handle && handle.done()) { + if (handle.promise().exception) { + std::rethrow_exception(handle.promise().exception); + } + return std::move(handle.promise().value); + } + throw std::runtime_error("Coroutine not completed"); + } +}; + +// 简单的协程函数,打印"Hello, ",然后挂起,恢复后打印"Coroutine!" +task hello_coroutine() { + std::cout << "Hello, "; + co_await std::suspend_always{}; // 挂起协程 + std::cout << "Coroutine!\n"; + co_return "Hello from coroutine"; +} + +int main() { + auto coro = hello_coroutine(); // 创建协程,此时协程被挂起 + std::cout << "Coroutine created\n"; + coro.resume(); // 恢复协程执行,打印"Hello, " + std::cout << "Coroutine resumed\n"; + coro.resume(); // 再次恢复协程执行,打印"Coroutine!" + std::cout << "Coroutine completed\n"; + std::cout << "Result: " << coro.get_result() << std::endl; + return 0; +} diff --git a/modern_cpp_coroutine/task_scheduler.cpp b/modern_cpp_coroutine/task_scheduler.cpp new file mode 100644 index 00000000..52b4d5e7 --- /dev/null +++ b/modern_cpp_coroutine/task_scheduler.cpp @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include + +// 自定义task类型,用于封装协程的状态和结果 +template +struct task { + // promise_type是协程的核心,负责协程的初始化、挂起和恢复 + struct promise_type { + T value; + std::exception_ptr exception; + std::coroutine_handle handle; + + // 获取协程的返回对象 + task get_return_object() { + handle = std::coroutine_handle::from_promise(*this); + return task(handle); + } + + // 初始挂起状态,返回std::suspend_always表示协程创建后立即挂起 + std::suspend_always initial_suspend() { + return {}; + } + + // 最终挂起状态,返回std::suspend_always表示协程完成后挂起 + std::suspend_always final_suspend() noexcept { + return {}; + } + + // 处理协程的返回值 + void return_value(T v) { + value = std::move(v); + } + + // 处理协程中的异常 + void unhandled_exception() { + exception = std::current_exception(); + } + }; + + std::coroutine_handle handle; + + // 构造函数 + explicit task(std::coroutine_handle h) : handle(h) {} + + // 析构函数,确保协程被正确销毁 + ~task() { + if (handle) { + handle.destroy(); + } + } + + // 禁止拷贝构造和拷贝赋值 + task(const task&) = delete; + task& operator=(const task&) = delete; + + // 允许移动构造和移动赋值 + task(task&& other) noexcept : handle(other.handle) { + other.handle = nullptr; + } + + task& operator=(task&& other) noexcept { + if (this != &other) { + if (handle) { + handle.destroy(); + } + handle = other.handle; + other.handle = nullptr; + } + return *this; + } + + // 恢复协程执行 + bool resume() { + if (!handle || handle.done()) { + return false; + } + handle.resume(); + return !handle.done(); + } + + // 获取协程的结果 + T get_result() { + if (handle && handle.done()) { + if (handle.promise().exception) { + std::rethrow_exception(handle.promise().exception); + } + return std::move(handle.promise().value); + } + throw std::runtime_error("Coroutine not completed"); + } +}; + +// 任务调度器类,用于管理多个协程任务 +class task_scheduler { +public: + // 添加任务到调度器 + void add_task(task t) { + tasks_.emplace(std::move(t)); + } + + // 执行所有任务 + void run_all() { + while (!tasks_.empty()) { + auto& task = tasks_.front(); + bool completed = !task.resume(); + if (completed) { + try { + std::cout << "Task completed with result: " << task.get_result() << std::endl; + } catch (const std::exception& e) { + std::cout << "Task failed with exception: " << e.what() << std::endl; + } + tasks_.pop(); + } + } + } + +private: + std::queue> tasks_; +}; + +// 简单的协程任务,模拟耗时操作 +void do_something(task_scheduler& scheduler, int id, int delay) { + std::thread([&scheduler, id, delay]() { + std::this_thread::sleep_for(std::chrono::seconds(delay)); + scheduler.add_task([id]() -> task { + std::cout << "Task " << id << " running" << std::endl; + co_await std::suspend_always{}; + std::cout << "Task " << id << " completed" << std::endl; + co_return "Task " + std::to_string(id) + " result"; + }()); + }).detach(); +} + +int main() { + task_scheduler scheduler; + + // 添加多个任务到调度器 + do_something(scheduler, 1, 2); + do_something(scheduler, 2, 1); + do_something(scheduler, 3, 3); + + // 执行所有任务 + scheduler.run_all(); + + return 0; +} diff --git a/stl_performance_test/README.md b/stl_performance_test/README.md new file mode 100644 index 00000000..0ea9fc2f --- /dev/null +++ b/stl_performance_test/README.md @@ -0,0 +1,35 @@ +# STL Performance Test + +This directory contains performance tests for STL containers and algorithms. + +## Introduction + +The Standard Template Library (STL) is a powerful set of C++ template classes that provide general-purpose classes and functions with templates that implement many popular and commonly used algorithms and data structures. + +However, the performance of different STL containers and algorithms can vary significantly depending on the use case. This directory contains performance tests to help you choose the right container or algorithm for your specific needs. + +## Contents + +1. **vector_vs_list.cpp** - Performance comparison between vector and list +2. **sort_algorithms.cpp** - Performance comparison between different sort algorithms +3. **find_algorithms.cpp** - Performance comparison between different find algorithms +4. **map_vs_unordered_map.cpp** - Performance comparison between map and unordered_map +5. **string_performance.cpp** - Performance tests for string operations + +## Build and Run + +To build and run these examples, you need a C++ compiler (e.g., GCC, Clang, MSVC). + +```bash +# Build with GCC +g++ -std=c++17 vector_vs_list.cpp -o vector_vs_list +./vector_vs_list + +# Build with Clang +clang++ -std=c++17 vector_vs_list.cpp -o vector_vs_list +./vector_vs_list + +# Build with MSVC +cl /std:c++17 vector_vs_list.cpp +vector_vs_list.exe +``` \ No newline at end of file diff --git a/stl_performance_test/sort_algorithms.cpp b/stl_performance_test/sort_algorithms.cpp new file mode 100644 index 00000000..0cc34da1 --- /dev/null +++ b/stl_performance_test/sort_algorithms.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include + +// 测试排序算法性能 +template +double test_sort(SortFunc sort_func, const std::vector& data) { + auto start = std::chrono::high_resolution_clock::now(); + std::vector copy = data; + sort_func(copy); + auto end = std::chrono::high_resolution_clock::now(); + return std::chrono::duration(end - start).count(); +} + +int main() { + const int num_elements = 100000; + const int num_tests = 5; + + // 生成随机测试数据 + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, 999999); + std::vector data(num_elements); + for (int i = 0; i < num_elements; ++i) { + data[i] = dis(gen); + } + + // 测试std::sort + double sort_time = 0.0; + for (int i = 0; i < num_tests; ++i) { + sort_time += test_sort([](std::vector& v) { + std::sort(v.begin(), v.end()); + }, data); + } + sort_time /= num_tests; + + // 测试std::stable_sort + double stable_sort_time = 0.0; + for (int i = 0; i < num_tests; ++i) { + stable_sort_time += test_sort([](std::vector& v) { + std::stable_sort(v.begin(), v.end()); + }, data); + } + stable_sort_time /= num_tests; + + // 测试std::partial_sort (排序前半部分) + double partial_sort_time = 0.0; + for (int i = 0; i < num_tests; ++i) { + partial_sort_time += test_sort([](std::vector& v) { + std::partial_sort(v.begin(), v.begin() + v.size() / 2, v.end()); + }, data); + } + partial_sort_time /= num_tests; + + // 测试std::nth_element (找到中位数) + double nth_element_time = 0.0; + for (int i = 0; i < num_tests; ++i) { + nth_element_time += test_sort([](std::vector& v) { + std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end()); + }, data); + } + nth_element_time /= num_tests; + + // 测试std::sort_heap + double sort_heap_time = 0.0; + for (int i = 0; i < num_tests; ++i) { + sort_heap_time += test_sort([](std::vector& v) { + std::make_heap(v.begin(), v.end()); + std::sort_heap(v.begin(), v.end()); + }, data); + } + sort_heap_time /= num_tests; + + // 输出结果 + std::cout << "排序算法性能对比:" << std::endl; + std::cout << "元素数量: " << num_elements << std::endl; + std::cout << "测试次数: " << num_tests << std::endl; + std::cout << std::endl; + + std::cout << "std::sort: " << sort_time << " 秒" << std::endl; + std::cout << "std::stable_sort: " << stable_sort_time << " 秒" << std::endl; + std::cout << "std::partial_sort (前半部分): " << partial_sort_time << " 秒" << std::endl; + std::cout << "std::nth_element (中位数): " << nth_element_time << " 秒" << std::endl; + std::cout << "std::sort_heap: " << sort_heap_time << " 秒" << std::endl; + std::cout << std::endl; + + std::cout << "相对性能 (std::sort = 1.0):" << std::endl; + std::cout << "std::sort: 1.0" << std::endl; + std::cout << "std::stable_sort: " << stable_sort_time / sort_time << "x 慢" << std::endl; + std::cout << "std::partial_sort: " << partial_sort_time / sort_time << "x 慢" << std::endl; + std::cout << "std::nth_element: " << nth_element_time / sort_time << "x 慢" << std::endl; + std::cout << "std::sort_heap: " << sort_heap_time / sort_time << "x 慢" << std::endl; + + return 0; +} diff --git a/stl_performance_test/vector_vs_list.cpp b/stl_performance_test/vector_vs_list.cpp new file mode 100644 index 00000000..a0c8f429 --- /dev/null +++ b/stl_performance_test/vector_vs_list.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include + +// 测试插入性能 +template +double test_insert(Container& container, int num_elements) { + auto start = std::chrono::high_resolution_clock::now(); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, num_elements - 1); + + for (int i = 0; i < num_elements; ++i) { + int value = dis(gen); + container.push_back(value); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff = end - start; + return diff.count(); +} + +// 测试删除性能 +template +double test_delete(Container& container, int num_elements) { + auto start = std::chrono::high_resolution_clock::now(); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, container.size() - 1); + + for (int i = 0; i < num_elements; ++i) { + auto it = container.begin(); + std::advance(it, dis(gen)); + container.erase(it); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff = end - start; + return diff.count(); +} + +// 测试访问性能 +template +double test_access(Container& container, int num_elements) { + auto start = std::chrono::high_resolution_clock::now(); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, container.size() - 1); + + for (int i = 0; i < num_elements; ++i) { + int index = dis(gen); + auto it = container.begin(); + std::advance(it, index); + int value = *it; + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff = end - start; + return diff.count(); +} + +int main() { + const int num_elements = 10000; + const int num_tests = 10; + + // 测试vector性能 + std::vector vec; + double vec_insert_time = test_insert(vec, num_elements); + double vec_delete_time = test_delete(vec, num_elements / 10); + double vec_access_time = test_access(vec, num_elements); + + // 测试list性能 + std::list lst; + double lst_insert_time = test_insert(lst, num_elements); + double lst_delete_time = test_delete(lst, num_elements / 10); + double lst_access_time = test_access(lst, num_elements); + + // 输出结果 + std::cout << "Performance comparison between vector and list:" << std::endl; + std::cout << "Number of elements: " << num_elements << std::endl; + std::cout << "Number of tests: " << num_tests << std::endl; + std::cout << std::endl; + + std::cout << "Insertion time: " << std::endl; + std::cout << "vector: " << vec_insert_time << " seconds" << std::endl; + std::cout << "list: " << lst_insert_time << " seconds" << std::endl; + std::cout << "vector is " << lst_insert_time / vec_insert_time << "x faster" << std::endl; + std::cout << std::endl; + + std::cout << "Deletion time: " << std::endl; + std::cout << "vector: " << vec_delete_time << " seconds" << std::endl; + std::cout << "list: " << lst_delete_time << " seconds" << std::endl; + std::cout << "list is " << vec_delete_time / lst_delete_time << "x faster" << std::endl; + std::cout << std::endl; + + std::cout << "Access time: " << std::endl; + std::cout << "vector: " << vec_access_time << " seconds" << std::endl; + std::cout << "list: " << lst_access_time << " seconds" << std::endl; + std::cout << "vector is " << lst_access_time / vec_access_time << "x faster" << std::endl; + + return 0; +}