Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions cpp23_features_demo/README.md
Original file line number Diff line number Diff line change
@@ -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
```
40 changes: 40 additions & 0 deletions cpp23_features_demo/modules_demo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 模块接口单元:module_demo
// 模块声明
module module_demo;

// 导出公共接口
#include <iostream>
#include <string>

export namespace module_demo {
// 公共函数声明
void hello();
std::string get_message();
}

// 模块实现单元
module module_demo;

// 导入必要的头文件
#include <iostream>
#include <string>

// 实现公共函数
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;
}
59 changes: 59 additions & 0 deletions cpp23_features_demo/std_expected.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <iostream>
#include <expected>
#include <string>
#include <sstream>

// 尝试将字符串转换为整数,返回std::expected<int, std::string>
std::expected<int, std::string> 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<int, std::string>(std::unexpected(error));
});

// 使用transform()方法转换值
auto result3 = result1.transform([](int value) {
return value * 2;
});
if (result3) {
std::cout << "Transformed value: " << *result3 << std::endl;
}

return 0;
}
76 changes: 76 additions & 0 deletions cpp23_features_demo/std_mdspan.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <iostream>
#include <vector>
#include <mdspan>

// 打印多维数组
void print_mdspan(std::mdspan<int, std::dynamic_extent, std::dynamic_extent> 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<int> matrix_multiply(
std::mdspan<int, std::dynamic_extent, std::dynamic_extent> a,
std::mdspan<int, std::dynamic_extent, std::dynamic_extent> 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<int> result(rows * cols);
std::mdspan<int, std::dynamic_extent, std::dynamic_extent> 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<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::mdspan<int, std::dynamic_extent, std::dynamic_extent> 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<int> data2 = {1, 2, 3, 4, 5, 6};
std::mdspan<int, std::dynamic_extent, std::dynamic_extent> 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<int> result = matrix_multiply(m, m2);
std::mdspan<int, std::dynamic_extent, std::dynamic_extent> 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;
}
44 changes: 44 additions & 0 deletions cpp_memory_management/README.md
Original file line number Diff line number Diff line change
@@ -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之间的循环引用。
109 changes: 109 additions & 0 deletions cpp_memory_management/memory_leaks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <iostream>
#include <memory>
#include <vector>
#include <chrono>

// 内存泄漏示例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<Node> 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<Node> node1 = std::make_shared<Node>("Node 1");
std::shared_ptr<Node> node2 = std::make_shared<Node>("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<int> ptr = std::make_unique<int>(42);
std::cout << "Value of ptr: " << *ptr << std::endl;
// 不需要手动释放内存,unique_ptr会自动释放

// 使用shared_ptr避免异常情况下的内存泄漏
std::shared_ptr<int> ptr2 = std::make_shared<int>(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<Node2> 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<Node2> node3 = std::make_shared<Node2>("Node 3");
std::shared_ptr<Node2> node4 = std::make_shared<Node2>("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;
}
Loading