第41章 C++20/23/26新特性

41.1 C++20新特性

41.1.1 概念(Concepts)

概念是C++20中引入的一种约束模板参数的机制,它允许我们在编译时检查模板参数是否满足特定的要求。

41.1.1.1 基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <concepts>
#include <iostream>

// 定义一个概念
template <typename T>
concept Arithmetic = std::is_arithmetic_v<T>;

// 使用概念约束模板参数
template <Arithmetic T>
T add(T a, T b) {
return a + b;
}

// 使用requires子句定义更复杂的概念
template <typename T>
concept Printable = requires(T t) {
{ std::cout << t } -> std::same_as<std::ostream&>;
};

template <Printable T>
void print(T t) {
std::cout << t << std::endl;
}

int main() {
std::cout << add(1, 2) << std::endl; // 正确
std::cout << add(1.5, 2.5) << std::endl; // 正确
// add("1", "2"); // 编译错误,字符串不是算术类型

print(42); // 正确
print(3.14); // 正确
print("Hello"); // 正确

return 0;
}

41.1.1.2 标准概念库

C++20提供了丰富的标准概念,定义在<concepts>头文件中:

  • std::integral:整型类型
  • std::floating_point:浮点型类型
  • std::same_as:类型相同
  • std::derived_from:派生自某个类型
  • std::convertible_to:可转换为某个类型
  • std::invocable:可调用对象
  • std::range:范围类型

41.1.2 模块(Modules)

模块是C++20中引入的一种新的代码组织方式,它替代了传统的头文件包含机制,提供了更好的编译性能和命名空间管理。

41.1.2.1 模块的基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 模块定义文件:math.cppm
export module math;

export int add(int a, int b) {
return a + b;
}

export double multiply(double a, double b) {
return a * b;
}

// 使用模块的文件:main.cpp
import math;
#include <iostream>

int main() {
std::cout << add(1, 2) << std::endl;
std::cout << multiply(2.5, 3.5) << std::endl;
return 0;
}

41.1.2.2 模块的优势

  • 编译性能:模块只需要编译一次,后续使用时直接引用编译结果
  • 命名空间隔离:模块中的名称不会污染全局命名空间
  • 依赖管理:明确的依赖关系,避免了头文件的循环包含
  • 接口清晰:通过export关键字明确导出的接口

41.1.3 协程(Coroutines)

协程是C++20中引入的一种轻量级线程,它允许函数在执行过程中暂停并在稍后恢复执行。

41.1.3.1 基本语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <coroutine>
#include <iostream>
#include <future>

// 协程返回类型
template <typename T>
struct task {
struct promise_type {
T value;
std::coroutine_handle<promise_type> handle;

task get_return_object() {
return task{std::coroutine_handle<promise_type>::from_promise(*this)};
}

std::suspend_never initial_suspend() noexcept {
return {};
}

std::suspend_never final_suspend() noexcept {
return {};
}

void return_value(T v) {
value = v;
}

void unhandled_exception() {
std::terminate();
}
};

std::coroutine_handle<promise_type> handle;

T get() {
return handle.promise().value;
}

~task() {
if (handle) handle.destroy();
}
};

// 协程函数
task<int> async_add(int a, int b) {
std::cout << "Async add started" << std::endl;
co_await std::suspend_always{}; // 暂停执行
std::cout << "Async add resumed" << std::endl;
co_return a + b; // 返回结果并结束协程
}

int main() {
auto t = async_add(1, 2);
std::cout << "Main thread continues" << std::endl;
// 恢复协程执行
t.handle.resume();
std::cout << "Result: " << t.get() << std::endl;
return 0;
}

41.1.3.2 协程的应用场景

  • 异步I/O:避免线程阻塞
  • 生成器:按需生成序列
  • 状态机:简化状态管理
  • 协作式多任务:轻量级线程

41.1.4 范围库(Ranges)

范围库是C++20中引入的一种新的迭代器抽象,它提供了更简洁、更灵活的方式来处理序列。

41.1.4.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <ranges>
#include <vector>
#include <iostream>
#include <algorithm>

int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 使用范围适配器
auto even_numbers = numbers | std::views::filter([](int n) { return n % 2 == 0; });

// 使用范围算法
std::ranges::for_each(even_numbers, [](int n) {
std::cout << n << " ";
});
std::cout << std::endl;

// 链式操作
auto result = numbers
| std::views::filter([](int n) { return n > 3; })
| std::views::transform([](int n) { return n * 2; })
| std::views::take(3);

std::ranges::for_each(result, [](int n) {
std::cout << n << " ";
});
std::cout << std::endl;

return 0;
}

41.1.4.2 常用范围适配器

  • std::views::filter:过滤元素
  • std::views::transform:转换元素
  • std::views::take:取前N个元素
  • std::views::drop:跳过前N个元素
  • std::views::reverse:反转序列
  • std::views::join:连接序列
  • std::views::zip:合并多个序列

41.1.5 三路比较运算符(<=>

三路比较运算符是C++20中引入的一种新运算符,它可以同时比较两个值的大小关系。

41.1.5.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <compare>
#include <iostream>

struct Point {
int x, y;

// 自动生成所有比较运算符
auto operator<=>(const Point&) const = default;
};

int main() {
Point a{1, 2};
Point b{1, 3};
Point c{2, 1};

std::cout << "a < b: " << (a < b) << std::endl;
std::cout << "a == b: " << (a == b) << std::endl;
std::cout << "a > c: " << (a > c) << std::endl;

// 使用三路比较的结果
auto result = a <=> b;
if (result < 0) {
std::cout << "a < b" << std::endl;
} else if (result == 0) {
std::cout << "a == b" << std::endl;
} else {
std::cout << "a > b" << std::endl;
}

return 0;
}

41.1.5.2 自定义三路比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <compare>
#include <string>
#include <iostream>

struct Person {
std::string name;
int age;

// 自定义三路比较
auto operator<=>(const Person& other) const {
if (auto cmp = name <=> other.name; cmp != 0) {
return cmp;
}
return age <=> other.age;
}

// 显式默认等于运算符
bool operator==(const Person& other) const = default;
};

int main() {
Person p1{"Alice", 30};
Person p2{"Bob", 25};
Person p3{"Alice", 28};

std::cout << "p1 < p2: " << (p1 < p2) << std::endl;
std::cout << "p1 > p3: " << (p1 > p3) << std::endl;
std::cout << "p1 == p3: " << (p1 == p3) << std::endl;

return 0;
}

41.1.6 consteval和constinit

C++20引入了两个新的关键字:constevalconstinit,用于控制常量表达式的计算时机。

41.1.6.1 consteval

consteval关键字用于声明一个立即函数,该函数必须在编译时求值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

// 立即函数,必须在编译时求值
consteval int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}

int main() {
// 编译时计算
constexpr int f5 = factorial(5);
std::cout << "5! = " << f5 << std::endl;

// 运行时计算会编译错误
// int n = 5;
// int fn = factorial(n); // 错误:参数不是常量表达式

return 0;
}

41.1.6.2 constinit

constinit关键字用于声明一个变量,该变量必须在编译时初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

// 编译时初始化
constinit int global_var = 42;

// 常量表达式函数
constexpr int compute() {
return 100;
}

int main() {
// 编译时初始化
constinit int local_var = compute();

std::cout << "global_var: " << global_var << std::endl;
std::cout << "local_var: " << local_var << std::endl;

// 修改constinit变量
global_var = 100;
local_var = 200;

std::cout << "global_var after modification: " << global_var << std::endl;
std::cout << "local_var after modification: " << local_var << std::endl;

return 0;
}

41.1.7 std::span

std::span是C++20中引入的一种非拥有式的容器视图,它提供了对连续内存的安全访问。

41.1.7.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <span>
#include <vector>
#include <array>
#include <iostream>

// 使用span作为函数参数
void print_elements(std::span<int> elements) {
for (int element : elements) {
std::cout << element << " ";
}
std::cout << std::endl;
}

int main() {
// 从vector创建span
std::vector<int> vec = {1, 2, 3, 4, 5};
std::span<int> vec_span(vec);
print_elements(vec_span);

// 从array创建span
std::array<int, 3> arr = {6, 7, 8};
std::span<int> arr_span(arr);
print_elements(arr_span);

// 从原始数组创建span
int raw_arr[] = {9, 10, 11};
std::span<int> raw_span(raw_arr);
print_elements(raw_span);

// 创建子span
std::span<int> sub_span = vec_span.subspan(1, 3); // 从索引1开始,取3个元素
print_elements(sub_span);

return 0;
}

41.1.7.2 span的优势

  • 非拥有式:不管理内存,只是视图
  • 类型安全:提供类型安全的访问
  • 边界检查:在调试模式下提供边界检查
  • 灵活:可以从各种容器创建

41.1.8 std::format

std::format是C++20中引入的一种新的格式化输出函数,它提供了类似Python的格式化语法。

41.1.8.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <format>
#include <string>
#include <iostream>

int main() {
// 基本格式化
std::string s1 = std::format("Hello, {}", "world");
std::cout << s1 << std::endl;

// 位置参数
std::string s2 = std::format("{}, {} and {}", "Alice", "Bob", "Charlie");
std::cout << s2 << std::endl;

// 命名参数
std::string s3 = std::format("{name} is {age} years old",
std::make_format_args("name"_a="Alice", "age"_a=30));
std::cout << s3 << std::endl;

// 格式化数字
std::string s4 = std::format("Pi is approximately {:.2f}", 3.14159);
std::cout << s4 << std::endl;

// 格式化日期时间
auto now = std::chrono::system_clock::now();
std::string s5 = std::format("Current time: {:%Y-%m-%d %H:%M:%S}", now);
std::cout << s5 << std::endl;

return 0;
}

41.1.8.2 格式化说明符

  • 宽度{:10} 表示宽度为10
  • 对齐{:<10} 左对齐,{:^10} 居中,{:>10} 右对齐
  • 填充{:*>10} 用*填充
  • 精度{:.2f} 小数点后2位
  • 进制{:x} 十六进制,{:o} 八进制,{:b} 二进制

41.1.9 std::jthread

std::jthread是C++20中引入的一种新的线程类,它是std::thread的改进版本,会自动管理线程的生命周期。

41.1.9.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <thread>
#include <iostream>
#include <chrono>

int main() {
// 创建jthread
std::jthread t([]() {
for (int i = 0; i < 5; ++i) {
std::cout << "Thread working... " << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});

// jthread会自动join,不需要手动调用join()
std::cout << "Main thread continues" << std::endl;

// 等待一段时间
std::this_thread::sleep_for(std::chrono::seconds(3));

// 可以请求线程停止
t.request_stop();

std::cout << "Main thread exiting" << std::endl;
// jthread会在析构时自动join
return 0;
}

41.1.9.2 jthread的优势

  • 自动join:在析构时自动join,避免线程泄漏
  • 可停止:支持请求线程停止
  • RAII:符合RAII原则

41.1.10 其他C++20特性

  • 初始化语句在if/switch中

    1
    2
    3
    4
    5
    if (auto [ptr, ec] = open_file("test.txt"); ec) {
    std::cerr << "Error opening file: " << ec.message() << std::endl;
    } else {
    // 使用ptr
    }
  • 指定初始化器

    1
    2
    3
    4
    5
    struct Point {
    int x, y;
    };

    Point p = {.x = 1, .y = 2};
  • constexpr lambda

    1
    2
    3
    4
    5
    constexpr auto add = [](int a, int b) {
    return a + b;
    };

    constexpr int result = add(1, 2); // 编译时计算
  • lambda中的this捕获

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct MyClass {
    int value = 42;

    auto getLambda() {
    // 显式捕获this
    return [*this]() {
    return value;
    };
    }
    };

41.2 C++23新特性

41.2.1 std::expected

std::expected是C++23中引入的一种新类型,它可以表示成功的值或错误信息。

41.2.1.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <expected>
#include <string>
#include <iostream>

std::expected<int, std::string> divide(int a, int b) {
if (b == 0) {
return std::unexpected("Division by zero");
}
return a / b;
}

int main() {
auto result1 = divide(10, 2);
if (result1) {
std::cout << "Result: " << *result1 << std::endl;
} else {
std::cout << "Error: " << result1.error() << std::endl;
}

auto result2 = divide(10, 0);
if (result2) {
std::cout << "Result: " << *result2 << std::endl;
} else {
std::cout << "Error: " << result2.error() << std::endl;
}

return 0;
}

41.2.1.2 链式操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <expected>
#include <string>
#include <iostream>

std::expected<int, std::string> parse_int(const std::string& s) {
try {
return std::stoi(s);
} catch (...) {
return std::unexpected("Invalid integer");
}
}

std::expected<int, std::string> add_one(int n) {
if (n < 0) {
return std::unexpected("Negative number");
}
return n + 1;
}

int main() {
std::string input = "42";

auto result = parse_int(input)
.and_then(add_one)
.and_then([](int n) {
return add_one(n);
});

if (result) {
std::cout << "Result: " << *result << std::endl;
} else {
std::cout << "Error: " << result.error() << std::endl;
}

return 0;
}

41.2.2 std::mdspan

std::mdspan是C++23中引入的一种多维数组视图,它提供了对连续内存的多维访问。

41.2.2.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <mdspan>
#include <vector>
#include <iostream>

int main() {
// 创建一个二维数组
std::vector<int> data = {1, 2, 3, 4, 5, 6};

// 创建mdspan视图
std::mdspan<int, std::extents<size_t, 2, 3>> matrix(data.data());

// 访问元素
matrix(0, 0) = 10;
matrix(1, 2) = 20;

// 遍历二维数组
for (size_t i = 0; i < matrix.extent(0); ++i) {
for (size_t j = 0; j < matrix.extent(1); ++j) {
std::cout << matrix(i, j) << " ";
}
std::cout << std::endl;
}

return 0;
}

41.2.2.2 动态维度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <mdspan>
#include <vector>
#include <iostream>

int main() {
// 创建一个三维数组
std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8};

// 创建动态维度的mdspan
std::mdspan<int, std::extents<size_t, 2, 2, 2>> tensor(data.data());

// 访问元素
tensor(0, 1, 0) = 100;

// 遍历三维数组
for (size_t i = 0; i < tensor.extent(0); ++i) {
for (size_t j = 0; j < tensor.extent(1); ++j) {
for (size_t k = 0; k < tensor.extent(2); ++k) {
std::cout << tensor(i, j, k) << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}

return 0;
}

41.2.3 std::print

std::print是C++23中引入的一种新的输出函数,它直接将格式化的内容输出到标准输出。

41.2.3.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <print>

int main() {
// 基本输出
std::print("Hello, {}\n", "world");

// 多个参数
std::print("{}, {} and {}\n", "Alice", "Bob", "Charlie");

// 格式化数字
std::print("Pi is approximately {:.2f}\n", 3.14159);

// 格式化宽度和对齐
std::print("{:<10} {:>10}\n", "Left", "Right");

return 0;
}

41.2.3.2 std::println

std::printlnstd::print的变体,它会自动添加换行符。

1
2
3
4
5
6
7
#include <print>

int main() {
std::println("Hello, {}", "world");
std::println("The answer is {}", 42);
return 0;
}

41.2.4 其他C++23特性

  • deducing this

    1
    2
    3
    4
    5
    6
    7
    struct MyClass {
    int value = 42;

    auto getValue(this auto&& self) {
    return self.value;
    }
    };
  • std::optional的monadic操作

    1
    2
    3
    4
    std::optional<int> o = 42;
    auto result = o.and_then([](int n) {
    return std::optional<int>(n + 1);
    });
  • std::string的contains方法

    1
    2
    3
    4
    std::string s = "Hello, world";
    if (s.contains("world")) {
    // 处理包含的情况
    }
  • std::vector的resize_and_overwrite

    1
    2
    3
    4
    5
    6
    7
    std::vector<int> v;
    v.resize_and_overwrite(10, [](int* ptr, size_t size) {
    for (size_t i = 0; i < size; ++i) {
    ptr[i] = i;
    }
    return size;
    });

41.3 C++26新特性

41.3.1 静态反射

静态反射是C++26中引入的一种新特性,它允许在编译时获取类型的信息。

41.3.1.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <reflect>
#include <iostream>

struct Point {
int x, y;
};

int main() {
// 获取类型信息
constexpr auto point_type =反射::type_of<Point>();

// 遍历成员变量
for_each(point_type.members(), [](auto member) {
std::cout << "Member: " << member.name() << std::endl;
std::cout << "Type: " << member.type().name() << std::endl;
});

// 创建对象并访问成员
Point p{1, 2};
auto x_member = point_type.member("x");
x_member.set(p, 10);
std::cout << "p.x = " << x_member.get(p) << std::endl;

return 0;
}

41.3.1.2 反射的应用

  • 序列化/反序列化:自动生成序列化代码
  • 对象关系映射:自动生成数据库映射代码
  • 依赖注入:自动生成依赖注入代码
  • 属性系统:实现类似C#的属性系统

41.3.2 模式匹配

模式匹配是C++26中引入的一种新特性,它允许在switch语句和if语句中使用更灵活的模式。

41.3.2.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <variant>
#include <string>
#include <iostream>

using Value = std::variant<int, double, std::string>;

void process(Value v) {
// 使用模式匹配
switch (v) {
case int i:
std::cout << "Integer: " << i << std::endl;
break;
case double d:
std::cout << "Double: " << d << std::endl;
break;
case std::string s:
std::cout << "String: " << s << std::endl;
break;
}
}

int main() {
process(42);
process(3.14);
process("Hello");
return 0;
}

41.3.2.2 结构化绑定模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct Point {
int x, y;
};

void process(Point p) {
// 使用结构化绑定模式
switch (p) {
case Point{0, 0}:
std::cout << "Origin" << std::endl;
break;
case Point{x: 0}:
std::cout << "On y-axis" << std::endl;
break;
case Point{y: 0}:
std::cout << "On x-axis" << std::endl;
break;
default:
std::cout << "Other point" << std::endl;
break;
}
}

41.3.3 网络库

网络库是C++26中引入的一种新的标准库,它提供了跨平台的网络编程功能。

41.3.3.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <network>
#include <iostream>

int main() {
// 创建TCP服务器
network::tcp::server server(8080);

server.on_accept([](auto client) {
std::cout << "Client connected" << std::endl;

client.on_read([](auto data) {
std::cout << "Received: " << std::string(data.begin(), data.end()) << std::endl;
});

client.on_disconnect([] {
std::cout << "Client disconnected" << std::endl;
});
});

std::cout << "Server listening on port 8080" << std::endl;
server.run();

return 0;
}

41.3.3.2 HTTP客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <network>
#include <iostream>

int main() {
// 创建HTTP客户端
network::http::client client;

// 发送GET请求
auto response = client.get("https://example.com");

std::cout << "Status: " << response.status() << std::endl;
std::cout << "Body: " << response.body() << std::endl;

return 0;
}

41.3.4 执行策略

执行策略是C++26中引入的一种新特性,它允许在算法中指定执行方式。

41.3.4.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <algorithm>
#include <execution>
#include <vector>
#include <iostream>

int main() {
std::vector<int> v = {5, 2, 8, 1, 9, 3};

// 顺序执行
std::sort(std::execution::seq, v.begin(), v.end());

// 并行执行
std::sort(std::execution::par, v.begin(), v.end());

// 并行无序执行
std::sort(std::execution::par_unseq, v.begin(), v.end());

for (int n : v) {
std::cout << n << " ";
}
std::cout << std::endl;

return 0;
}

41.3.5 数学库增强

C++26中对数学库进行了增强,添加了许多新的数学函数。

41.3.5.1 基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <cmath>
#include <iostream>

int main() {
// 新的数学函数
double x = 0.5;

std::cout << "erfcinv(" << x << ") = " << std::erfcinv(x) << std::endl;
std::cout << "expint(" << x << ") = " << std::expint(x) << std::endl;
std::cout << "riemann_zeta(" << x << ") = " << std::riemann_zeta(x) << std::endl;

return 0;
}

41.3.6 其他C++26特性

  • 协程的改进

    • 更简洁的协程语法
    • 标准协程库
  • 模块的改进

    • 内联模块
    • 模块分区
  • 类型推断的改进

    • auto在更多上下文中的使用
    • 更智能的模板参数推断
  • 安全性增强

    • 更严格的边界检查
    • 更安全的内存访问

41.4 现代C++的最佳实践

41.4.1 代码风格

  • 使用概念:优先使用概念而不是SFINAE
  • 使用模块:优先使用模块而不是头文件
  • 使用范围库:优先使用范围库而不是原始迭代器
  • 使用std::format:优先使用std::format而不是printfstd::cout的复杂格式化
  • 使用std::expected:优先使用std::expected处理可能失败的操作

41.4.2 性能优化

  • 使用std::span:避免不必要的复制
  • 使用consteval:将计算移到编译时
  • 使用constinit:避免运行时初始化
  • 使用协程:避免线程阻塞
  • 使用执行策略:利用并行计算

41.4.3 安全性

  • 使用std::jthread:避免线程泄漏
  • 使用std::optionalstd::expected:避免空指针和错误处理
  • 使用边界检查:避免越界访问
  • 使用RAII:确保资源正确管理

41.5 总结

C++20、C++23和C++26标准引入了许多新特性,这些特性使得C++更现代化、更安全、更高效:

  • C++20:概念、模块、协程、范围库、三路比较运算符、consteval、constinit、span、format、jthread
  • C++23:std::expected、std::mdspan、std::print、deducing this、monadic操作
  • C++26:静态反射、模式匹配、网络库、执行策略、数学库增强

这些新特性不仅提高了代码的可读性和可维护性,也提供了更好的性能和安全性。作为现代C++程序员,我们应该积极学习和使用这些新特性,以编写更优质的C++代码。

同时,我们也应该注意保持代码的兼容性,对于需要支持旧编译器的项目,应该谨慎使用这些新特性,或者使用条件编译来处理不同的编译器版本。

通过不断学习和实践现代C++的新特性,我们可以充分发挥C++的优势,编写更加高效、安全、可维护的代码。