C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++20新特性

一文详解C++20新特性

作者:剑锋所指,所向披靡!

本文主要介绍了一文详解C++20新特性,包括模块、协程、范围、日期时区、格式化等并发等特性介绍,替代头文件、提升编译效率、支持异步逻辑、增强日期处理、类型安全格式化及简化并发编程

1、模块

C++ 20 中正式引入了模块的概念,模块是一个用于在翻译单元间分享声明和定义的语言特性。它们可以在某些地方替代使用头文件。
其主要优点如下:

  1. 没有头文件。
  2. 声明实现仍然可分离, 但非必要。
  3. 可以显式指定导出哪些类或函数。
  4. 不需要头文件重复引入宏(include guards)。
  5. 模块之间名称可以相同,并且不会冲突。
  6. 模块只处理一次,编译更快(头文件每次引入都需要处理,需要通过 pragma once 约束)。7. 预处理宏只在模块内有效。
  7. 模块的引入与引入顺序无关。

用法

  1. 定义模块(math.ixx)
// 模块声明(模块名:math)
export module math;

// 导出函数(外部可访问)
export int add(int a, int b) {
    return a + b;
}

// 内部函数(仅模块内可见)
int mul(int a, int b) {
    return a * b;
}
  1. 使用模块(main.cpp)
// 导入模块(无需头文件,直接用)
import math;
#include <iostream>

int main() {
    std::cout << add(2, 3) << std::endl; // 输出5(可访问导出的add)
    // std::cout << mul(2, 3) << std::endl; // 编译错误:mul未导出
    return 0;
}

2、协程

C++20 引入无栈协程(非协程库,仅底层机制),是可挂起 / 恢复的特殊函数(非 main 函数),支持用同步写法实现异步逻辑;函数内含co_await/co_yield/co_return任一关键字即为协程,协程不抢占内核调度,仅由线程调用。

关键字作用
co_yield some_value挂起协程并保存状态,向调用者返回some_value
co_await some_awaitable若some_awaitable未就绪,挂起协程并保存状态;就绪后恢复执行
co_return some_value终止协程,向调用者返回some_value(协程彻底结束)

3、<=> 三向比较运算符

比较结果如下
(a <=> b) < 0 // 如果 a < b 则为 true
(a <=> b) > 0 // 如果 a > b 则为 true
(a <=> b) == 0 // 如果 a 与 b 相等或者等价 则为 true
类似于C的strcmp 函数返回-1, 0, 1
一般情况: 自动生成所有的比较操作符, 如果对象是结构体则逐个比较, 可以用下面代码代替所有的比较运算符

auto X::operator<=>(const Y&) = default;
int num1 = 100, num2 = 100;
if ((num1 <=> num2) < 0) {
cout << "num1 < num2" << endl;}
else if ((num1 <=> num2) > 0) {
cout << "num1 > num2" << endl;}
else {
cout << "num1 = num2" << endl;}

4、范围 ranges

C++20 引入std::ranges(范围库),是对传统 STL 算法的增强,以 “范围”(容器、数组、视图等)为核心,简化遍历 / 算法调用,支持链式操作,且兼容原有 STL 容器,大幅提升代码简洁性和可读性。

#include <ranges>
#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> vec = {1,2,3,4,5};
    // 范围遍历:自动迭代,无需手动写begin()/end()
    for (int i : vec | ranges::views::filter([](int x){ return x%2==0; })) {
        cout << i << " "; // 输出:2 4
    }
    return 0;
}

5、日期和时区

C++20 引入std::chrono增强的日期 / 时区库,首次标准化了日期(年 / 月 / 日)、时间(时 / 分 / 秒)和时区的统一处理,替代传统零散的时间操作方式,支持本地时间、UTC 时间、时区转换等核心能力。

#include <chrono>
#include <iostream>
using namespace std;
using namespace chrono;

int main() {
    // 1. 获取当前系统时间(UTC)
    auto now_utc = system_clock::now();
    // 转换为日期(年/月/日)
    year_month_day ymd = floor<days>(now_utc);
    cout << ymd.year() << "-" << ymd.month() << "-" << ymd.day() << endl;

    // 2. 时区转换(UTC→本地时区)
    zoned_time local_tz{current_zone(), now_utc};
    cout << "本地时间:" << local_tz << endl;

    return 0;
}

6、格式化

C++20 引入std::format(格式化库),替代传统的printf/cout拼接,支持类型安全的字符串格式化

#include <format>
#include <string>
#include <iostream>
using namespace std;

int main() {
    // 基础格式化:替代printf("%d + %d = %d", a, b, a+b)
    int a = 5, b = 3;
    string res = format("{} + {} = {}", a, b, a + b);
    cout << res << endl; // 输出:5 + 3 = 8

    // 带格式控制(指定宽度、精度、进制)
    cout << format("数字:{:5d},十六进制:{:x},浮点数:{:.2f}", 123, 255, 3.1415) << endl;
    // 输出:数字:  123,十六进制:ff,浮点数:3.14

    return 0;
}

7、跨度

C++20 引入std::span(跨度),是对连续内存区域(数组、vector、C 数组等)的「轻量级只读 / 可写视图」,仅存储指针 + 长度,无内存拷贝,可安全替代裸指针 / 数组,简化连续内存的访问与传递。

#include <span>
#include <vector>
#include <iostream>
using namespace std;

// 替代传统的「指针+长度」传参,更安全
void print_span(span<int> s) {
    for (int i : s) cout << i << " ";
}

int main() {
    int arr[] = {1,2,3,4};
    vector<int> vec = {5,6,7};
    
    // 1. 绑定数组(自动推导长度)
    span<int> s1(arr); 
    print_span(s1); // 输出:1 2 3 4
    
    // 2. 绑定vector(无拷贝,仅视图)
    span<int> s2(vec);
    s2[0] = 10; // 修改视图会同步修改原vector
    cout << vec[0] << endl; // 输出:10
    
    // 3. 切片(取部分元素)
    span<int> s3 = s1.subspan(1, 2); // 从索引1开始,取2个元素
    print_span(s3); // 输出:2 3
    
    return 0;
}

8、并发

C++20 在原有并发基础上增强了并发能力,核心新增std::jthread(可自动 join 的线程)、std::latch/barrier(同步原语)、std::stop_token(线程取消机制),同时完善原子操作和异步任务,让并发编程更安全、易用,减少手动管理线程的出错风险。

  1. std::jthread(安全线程,替代 std::thread)增强版线程,析构自动 join,支持取消
#include <jthread>
#include <iostream>
using namespace std;

void task(int n) {
    cout << "线程执行:" << n << endl;
}

int main() {
    // jthread析构时自动join,无需手动调用(避免std::thread的析构崩溃)
    jthread t(task, 10); 
    // 无需写t.join(),t销毁时自动完成
    return 0;
}
  1. 线程取消(stop_token + jthread)配合 jthread 实现安全的线程取消
void cancelable_task(stop_token st, int n) {
    for (int i=0; i<n; ++i) {
        // 检查是否收到取消信号
        if (st.stop_requested()) {
            cout << "线程被取消" << endl;
            return;
        }
        cout << "执行中:" << i << endl;
    }
}

int main() {
    jthread t(cancelable_task, 100);
    // 发送取消信号
    t.request_stop(); 
    return 0;
}
  1. std::latch(一次性同步屏障)一次性同步屏障,等待指定数量线程就绪
#include <latch>
#include <vector>

int main() {
    latch l(3); // 需3个线程到达后,主线程才继续
    vector<jthread> threads;
    
    for (int i=0; i<3; ++i) {
        threads.emplace_back([&l, i]() {
            cout << "线程" << i << "就绪" << endl;
            l.count_down(); // 计数减1
        });
    }
    l.wait(); // 等待所有线程就绪
    cout << "所有线程就绪,主线程继续" << endl;
    return 0;
}

到此这篇关于一文详解C++20新特性的文章就介绍到这了,更多相关C++20新特性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文