• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2024-06-30 17:12 Aet 隐藏边栏 |   抢沙发  3 
文章评分 3 次,平均分 5.0

语言特性

概念Concepts

概述

  1. 概念用于约束模板参数,提供了一种简洁的方式来指定模板参数的要求
  2. 约束模板参数,增强代码可读性和错误提示

示例

  1. 示例1

  1. 示例2

范围库(Ranges

概述

  1. 提供声明式数据操作,支持惰性求值和链式调用

示例

  1. 过滤偶数并平方

协程(Coroutines)

概述

  1. C++20 引入的一种新特性,提供了一种可以暂停和恢复的函数形式,使得编写异步代码更加简单和直观
    1. 协程通过 co_awaitco_yieldco_return 等关键字来实现,能够在异步编程、生成器、任务调度等场景中发挥作用

概念

  1. 协程函数:
    1. 包含 co_awaitco_yieldco_return 关键字的函数被称为协程函数
    2. 协程函数的返回类型必须是支持协程的类型,如 std::coroutine_handle 或用户自定义类型
  2. 协程句柄:
    1. std::coroutine_handle 是一个可以控制协程执行的句柄,允许暂停、恢复和销毁协程
  3. 协程承诺类型(Promise Type):
    1. 每个协程函数都有一个关联的承诺类型(promise type),它负责管理协程的状态、返回值和异常处理

协程生命周期

  1. 初始化
    1. 调用协程函数时,生成一个协程状态对象,并调用 initial_suspend 以决定协程是否立即挂起
  2. 执行
    1. 协程从挂起点恢复执行,直到遇到 co_awaitco_yieldco_return
  3. 挂起
    1. co_awaitco_yield 关键字会导致协程挂起,返回控制权给调用者
  4. 恢复
    1. 外部可以通过协程句柄恢复协程的执行
  5. 完成
    1. 协程执行到 co_return 或结尾时,调用 final_suspend,释放协程资源

示例1

  1. Task 构造函数接收一个 std::coroutine_handle<promise_type>,用于管理协程的生命周期
  2. Task 析构函数在协程句柄有效时销毁协程,以释放资源
  3. hello 协程函数:
    1. hello 中,co_await std::suspend_always{} 使协程在输出 Hello, 后挂起,需要显式恢复
  4. 恢复协程:
    1. main 函数中,通过 h.coro.resume() 恢复协程的执行,继续输出 World!\n

promise_type

  1. promise_type 是协程的核心部分,用于管理协程的状态
  2. 每个协程类型都必须定义一个嵌套的 promise_type 结构,该结构负责处理协程的创建、挂起、恢复和销毁
    1. 虽然具体的实现可以根据需要进行定制,但某些函数是固定的,因为它们是协程框架调用的接口
  3. get_return_object
    1. 这个函数用于返回协程的返回对象。它在协程开始时被调用

  1. initial_suspend
    1. 这个函数返回一个等待操作,决定协程在启动时是否挂起

  1. final_suspend
    1. 这个函数返回一个等待操作,决定协程在结束时是否挂起

  1. return_void / return_value
    1. 这两个函数用于处理协程的返回值
    2. return_void 用于没有返回值的协程,return_value 用于有返回值的协程

  1. unhandled_exception
    1. 这个函数用于处理协程中的未处理异常

示例2

  1. 生成斐波那契数列:

模块

概述

  1. 模块是 C++20 引入的一种新机制,用于替代传统的头文件,提供更好的编译性能和模块化支持
    1. 不需要传统的头文件
  2. 总的来说,就是替代头文件,提高编译速度,增强封装性

示例

  1. 示例1

三路比较运算符

  1. C++20 引入了三方比较运算符,用于统一和简化比较操作
  2. C++20 中,三方比较运算符可以自动生成

  1. auto operator<=>(const Point&) const = default;
    1. 告诉编译器为 Point 结构体自动生成三方比较运算符
    2. 意味着编译器会自动生成对 Point 结构体中所有成员变量
      (在这个例子中是 xy)的逐个比较操作
  2. 当编译器自动生成三方比较运算符时,它会按照成员声明的顺序依次比较每个成员,并返回第一个非零的比较结果
    1. 如果所有成员都相等,则比较结果为零
  3. 生成的比较运算符:
    1. operator<=>:用于 <=> 比较操作,返回 std::strong_ordering
    2. operator==:用于相等比较操作
  4. C++20 提供了几种不同的三方比较类型:
    1. std::strong_ordering:强序关系,适用于完全排序的类型(例如 intdouble
    2. std::weak_ordering:弱序关系,适用于可以相等但不完全排序的类型
    3. std::partial_ordering:部分序关系,适用于可能不完全比较的类型(例如 NaN
  5. 假如上面的Point结构体里面有个string
    1. std::string 类型本身已经支持三方比较运算符,因此编译器可以正确地生成比较运算符

constevalconstinit

概述

  1. C++20 引入了 constevalconstinit 两个关键字,分别用于增强编译期计算和初始化的控制

consteval(立即函数)

  1. 核心作用
    1. 声明函数为 必须编译期求值 的 立即函数(Immediate Function
    2. 函数只能在编译期调用,禁止运行时调用
    3. 用于强制生成编译期常量,替代 constexpr 函数在运行时可能被误用的场景
  2. 场景
    1. 必须生成编译期常量的计算(如查找表、加密密钥生成)
    2. 替代 constexpr 以禁止运行时调用
  3. 示例

constevalconstexpr 的区别

特性 constexpr 函数 consteval 函数
调用时机 允许编译期和运行时调用 必须编译期调用
返回值用途 可赋值给 constexpr 或普通变量 只能赋值给编译期已知的变量

constinit(强制编译期初始化)

  1. 核心作用

    1. 确保变量 在编译期完成初始化,避免静态初始化顺序问题
    2. 仅适用于 静态存储期变量(全局、staticthread_local
    3. 变量可以是 非常量,但必须用常量表达式初始化
    4. 替代 constexpr 定义需要运行时修改的全局变量
  2. 场景

    1. 解决跨编译单元的全局变量初始化顺序问题
  3. 示例1

constinitconstexpr 变量的区别

特性 constexpr 变量 constinit 变量
常量性 必须是常量 可以是变量(允许后续修改)
初始化要求 必须用常量表达式初始化 必须用常量表达式初始化
适用存储类型 不限 仅限静态存储期变量

联合示例

标准库新增组件

std::format

概述

  1. C++20 引入了 std::format,这是一个强大且灵活的字符串格式化工具,类似于 Pythonstr.format
  2. 它提供了一种类型安全、可读性好且高效的方式来格式化字符串

用法

  1. 用于格式化字符串,并返回一个格式化后的 std::string
  2. 使用大括号 {} 作为占位符,并支持多种格式化选项

数字格式化

  1. 整数

  1. 浮点数

  1. 字符串对齐和填充

命名参数

  1. 目前,std::format 不直接支持命名参数,但你可以使用结构绑定或 std::tuple 来实现类似功能

格式化类成员

自定义格式化

  1. 可以为自定义类型实现格式化支持,通过定义特化的 std::formatter 模板

std::span

  1. std::span 提供了一种视图类型,用于表示连续的内存块
    1. 非拥有视图,安全访问连续内存序列(如数组、向量)

日历和时区库(chrono扩展)

概述

  1. 处理日期和时间,支持时区转换

示例

std::jthreadstd::stop_token

概述

  1. C++20 引入了 std::jthreadstd::stop_token,用于更好的线程管理和停止操作

std::jthread

  1. C++20 引入的新型线程类,它的名字中的 "j" 代表 "joining"
  2. 与传统的 std::thread 不同,std::jthread 在析构时会自动等待(join)线程的结束,从而避免了某些常见的资源泄露和线程管理问题
  3. 特点:
    1. 自动 joinstd::jthread 在对象析构时自动调用 join()
    2. 支持停止请求:结合 std::stop_token 使用,可以优雅地请求线程停止

std::stop_token

  1. 线程函数通过它检查是否有停止请求
    1. 是一种新的机制,用于请求线程停止
  2. 它和 std::stop_sourcestd::stop_callback 一起使用,提供了一种更灵活的线程停止管理方式

std::stop_source

  1. 用于发出停止请求

std::stop_callback

  1. 用于在停止请求发出时执行回调
  2. 下面的示例中,在st上面注册了一个回调函数[](){...}
    1. t.request_stop();这一行运行后,会先调用注册的这个回调函数,然后再走道while循环这里的逻辑

其他重要改进

constexpr 改进

编译时计算

  1. C++20constexpr 进行了改进,允许更多的复杂表达式在编译时计算

编译期使用动态内存分配和虚函数

  1. 允许在编译期使用动态内存分配和虚函数

[[no_unique_address]]

  1. 优化空类成员的内存占用

位操作库(<bit>

概述

  1. C++20 引入了 <bit> 头文件,提供了一系列高效且可移植的位操作函数,涵盖位转换、循环移位、位计数和字节序处理等功能

std::bit_cast

  1. C++20 引入的一个标准库函数,用于进行类型安全的位级别转换(bitwise cast

    1. 安全地将对象的位模式转换为另一种类型,无需类型双关(Type Punning
    2. 它可以将一个对象的比特表示(bit representation)重新解释为另一种类型,而不改变对象的实际内存内容
    3. 这在需要进行底层操作或优化时非常有用,同时提供了类型安全性
  2. 要求

    1. 源类型和目标类型大小相同且均为可平凡复制(Trivially Copyable
  3. 定义

  1. 关键

    1. ToFrom 必须是同样大小的标准布局类型(standard-layout types
    2. To 必须是可平凡复制构造的(trivially copyable
    3. std::bit_cast 是一个常量表达式函数,这意味着它可以在编译时计算结果
  2. 示例

循环移位函数

  1. std::rotl(x, s):循环左移 s
  2. std::rotr(x, s):循环右移 s
  3. s 为负数,自动取模转换(如 rotl(x, -1) 等价于 rotl(x, sizeof(x)*8 - 1)

位计数函数

  1. std::countl_zero(x):从最高位开始连续 0 的个数(前导零)
  2. std::countr_zero(x):从最低位开始连续 0 的个数(末尾零)
  3. std::countl_one(x):从最高位开始连续 1 的个数
  4. std::countr_one(x):从最低位开始连续 1 的个数

std::popcount(统计置位数)

  1. 计算整数二进制表示中 1 的个数

字节序处理

  1. 枚举:std::endian
    1. std::endian::little:小端序
    2. std::endian::big:大端序
    3. std::endian::native:当前系统字节序

统一的调用约定(Uniform Call Syntax)

概述

  1. 允许成员函数和自由函数使用相同的语法调用
  2. C++20引入了 std::size 和其他类似的标准库函数,使得可以对标准容器和数组等数据结构统一地调用这些函数,而不必关心它们是成员函数还是全局函数

函数

  1. std::size:获取容器或数组的大小
  2. std::data:获取容器或数组的底层数据指针
  3. std::empty:检查容器或数组是否为空

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2025-03-21
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享