当前位置: 首页 > news >正文

C++20新特性的补充讲解

C++20 标志着 C++ 语言的一次重要更新,除了 Concepts、Ranges、协程等被广泛讨论的特性外,还有许多值得注意的改进。本文将详细探讨其他一些核心新特性,包括 constexpr 扩展、新增的 std::formatstd::spanstd::bit 操作、原子智能指针、char8_t 类型以及 lambda 表达式的改进等。通过这些特性,C++20 带来了更简洁、更高效的编程体验。

文章目录

    • @[toc]
    • 一、`constexpr` 扩展
      • 示例
    • 二、`std::format`:强大的字符串格式化
      • 示例
    • 三、`std::span`:安全的连续内存视图
      • 示例
    • 四、`std::bit` 操作库
      • 示例
    • 五、原子智能指针
      • 示例
    • 六、`char8_t` 类型
      • 示例
    • 七、lambda 表达式的改进
      • 1. 捕获 `this` 的改进
      • 2. 模板 lambda
    • 八、扩展的`[[nodiscard]]`属性
      • 示例
    • 九、改进的`std::chrono`库
      • 示例
    • 十、其他改进
      • 1. `std::source_location`
      • 2. `std::stop_token` 和 `std::jthread`
      • 3. 匿名结构体和联合体
    • 总结

一、constexpr 扩展

在 C++20 中,constexpr 关键字得到了进一步扩展,使得更多的操作可以在编译期执行。这意味着我们可以在 constexpr 中使用更复杂的代码,包括 try-catch 异常处理、动态分配和更多的标准库函数,使编译时常量计算的范围大大增加。

示例

#include <array>
#include <iostream>constexpr int factorial(int n) {if (n <= 1) return 1;return n * factorial(n - 1);
}int main() {constexpr int result = factorial(5); // 在编译期计算std::cout << result << std::endl;    // 输出:120return 0;
}

在这个例子中,我们利用 constexpr 计算阶乘函数 factorial。在 C++20 中,这种递归计算不仅更加灵活,还可以在编译期完成,为程序提供了额外的性能优化空间。


二、std::format:强大的字符串格式化

std::format 是 C++20 引入的一个重要新特性,类似于 Python 的 f-string 或者 printf 函数,提供了更现代、灵活的字符串格式化功能。std::format 使用占位符和格式说明符来简化字符串拼接操作,使代码更清晰。

示例

#include <format>
#include <iostream>int main() {int year = 2023;double pi = 3.14159;std::string formatted = std::format("The year is {} and Pi is {:.2f}.", year, pi);std::cout << formatted << std::endl;  // 输出:The year is 2023 and Pi is 3.14.return 0;
}

这里,std::format 使用 {} 作为占位符,支持指定宽度、精度等格式化参数。相比传统的 sprintf 函数,std::format 更加类型安全、功能更强大,提升了代码的可读性和安全性。


三、std::span:安全的连续内存视图

std::span 是一种轻量级的非拥有数据的容器视图,用于表示连续的内存块,例如数组或 std::vector 的某部分。std::span 提供了访问连续内存的方式,而不需要传递指针和大小参数,提高了接口的安全性和可读性。

示例

#include <span>
#include <iostream>void print(std::span<int> data) {for (int value : data) {std::cout << value << " ";}
}int main() {int arr[] = {1, 2, 3, 4, 5};print(arr); // 可以直接传入数组return 0;
}

std::span 的优势在于可以避免数组指针传递带来的边界不清问题,提供了更加一致和简洁的接口。它还可以与 std::vector 等容器结合使用,进一步增强代码的灵活性。


四、std::bit 操作库

C++20 新增了 std::bit 标准库,提供了一系列用于位操作的函数,包括按位旋转、按位计数等操作。这些操作对底层位操作有很大的帮助,简化了位处理的复杂度。

示例

#include <bit>
#include <iostream>int main() {unsigned int x = 0b0011'1100;// 位旋转操作unsigned int rotated = std::rotl(x, 2); // 左旋 2 位std::cout << "After left rotation: " << std::bitset<8>(rotated) << std::endl;// 计算 1 的数量int count = std::popcount(x);std::cout << "Number of 1s: " << count << std::endl;return 0;
}

这些位操作函数对需要处理位运算的程序员来说非常实用,提供了更高效、更简洁的位操作支持,适合于处理嵌入式系统和性能敏感的应用场景。


五、原子智能指针

C++20 引入了 std::atomic_shared_ptrstd::atomic_weak_ptr,使得智能指针能够以原子的方式操作。这一改进简化了并发编程中智能指针的管理,保证了多线程环境下的指针操作安全。

示例

#include <atomic>
#include <iostream>
#include <memory>
#include <thread>std::atomic<std::shared_ptr<int>> atomic_ptr;void thread1() {auto ptr = std::make_shared<int>(42);atomic_ptr.store(ptr);
}void thread2() {auto ptr = atomic_ptr.load();if (ptr) {std::cout << "Value: " << *ptr << std::endl;}
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();return 0;
}

原子智能指针的引入简化了多线程环境下共享资源的管理,确保了数据的线程安全,是并发编程中的一项重要改进。


六、char8_t 类型

C++20 引入了 char8_t 类型,用于表示 UTF-8 编码的字符。这一类型使得代码在处理多字节字符时更加清晰和安全,避免了传统 char 类型在编码上的模糊性。

示例

#include <iostream>void print_utf8(const char8_t* text) {while (*text) {std::cout << static_cast<char>(*text);text++;}
}int main() {const char8_t* text = u8"Hello, UTF-8!";print_utf8(text); // 输出:Hello, UTF-8!return 0;
}

char8_t 提供了更强的编码明确性,减少了因编码转换产生的错误和歧义,是现代应用程序处理 UTF-8 编码的理想选择。


七、lambda 表达式的改进

C++20 为 lambda 表达式带来了几项重要改进,包括捕获 this 指针的简化和 template lambda 支持,使得 lambda 更加灵活易用。

1. 捕获 this 的改进

在 C++20 之前,lambda 捕获成员变量的方式较为繁琐。C++20 允许直接捕获 *this,避免了冗长的捕获列表。

#include <iostream>struct MyClass {int value = 42;void show() {auto lambda = [*this] { std::cout << value << std::endl; };lambda();}
};int main() {MyClass obj;obj.show(); // 输出:42return 0;
}

2. 模板 lambda

模板 lambda 允许我们定义带模板参数的 lambda 表达式,适合泛型编程场景,使得 lambda 表达式更加灵活。

#include <iostream>int main() {auto add = []<typename T>(T a, T b) {return a + b;};std::cout << add(1, 2) << std::endl;       // 输出:3std::cout << add(1.5, 2.5) << std::endl;   // 输出:4.0return 0;
}

模板 lambda 为泛型编程提供了更简洁的写法,减少了冗长的函数模板定义,让代码更具表现力。


八、扩展的[[nodiscard]]属性

C++20 扩展了 [[nodiscard]] 属性,允许对整个类型或函数标记 [[nodiscard]],表示返回值不可忽略。通过这一属性,可以避免意外忽略重要返回值引起的潜在错误。

示例

#include <iostream>[[nodiscard]] int compute_important_value() {return 42;
}int main() {compute_important_value(); // 警告:忽略了 `nodiscard` 返回值return 0;
}

[[nodiscard]] 属性提高了代码的健壮性,使得重要返回值不会被意外忽略。它适用于那些返回值不可忽略的函数,比如错误处理、资源分配等场景。通过 [[nodiscard]] 属性,C++20 能够进一步减少因忽略关键返回值导致的潜在问题。


九、改进的std::chrono

C++20 对 std::chrono 时间库进行了改进,添加了对历法和时区的支持。这些改进使得处理日期和时间更加方便,尤其是在处理跨时区和复杂日期计算的应用中。

示例

#include <iostream>
#include <chrono>
#include <format>int main() {using namespace std::chrono;// 获取当前的系统时间auto now = system_clock::now();// 格式化输出日期和时间std::cout << std::format("Current time: {:%Y-%m-%d %H:%M:%S}\n", now);// 计算未来的日期auto future_date = now + days(100);std::cout << std::format("100 days later: {:%Y-%m-%d}\n", future_date);return 0;
}

std::chrono 的改进使得日期和时间的处理更加直观,避免了开发者使用外部库来实现类似功能。通过新的时区支持,C++20 让时间计算和显示更加精确和方便。


十、其他改进

除了上面提到的主要特性,C++20 还包含了许多小而实用的改进:

1. std::source_location

std::source_location 允许获取源代码的位置(如文件名、行号和函数名),用于日志和调试信息的记录,非常适合用于调试和错误跟踪。

#include <iostream>
#include <source_location>void log(const std::string& message, const std::source_location& location = std::source_location::current()) {std::cout << "Log: " << message<< " (" << location.file_name() << ":" << location.line() << " in " << location.function_name() << ")\n";
}int main() {log("An example message");return 0;
}

2. std::stop_tokenstd::jthread

std::stop_tokenstd::jthread 简化了线程的停止机制,支持安全的线程中断。std::jthread 自动管理线程的生命周期,避免了线程资源泄漏。

#include <iostream>
#include <thread>
#include <chrono>
#include <stop_token>void task(std::stop_token stop_token) {while (!stop_token.stop_requested()) {std::cout << "Working...\n";std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Task stopped.\n";
}int main() {std::jthread worker(task);  // 使用 jthread 运行线程std::this_thread::sleep_for(std::chrono::seconds(3));worker.request_stop();  // 请求线程停止return 0;
}

3. 匿名结构体和联合体

C++20 支持匿名结构体和联合体,允许在类中嵌套匿名的 structunion,从而简化代码结构。

#include <iostream>struct Point {union {struct {int x, y;};int coords[2];};
};int main() {Point p;p.x = 10;p.y = 20;std::cout << "Point x: " << p.coords[0] << ", y: " << p.coords[1] << std::endl;return 0;
}

匿名结构体和联合体在需要存储多个互斥数据时提供了更便捷的方式,使代码更加紧凑。


总结

C++20 是一次全面的更新,带来了 Concepts、Ranges、Coroutines 等重量级特性,同时通过 constexpr 扩展、std::formatstd::span、原子智能指针、std::chrono 改进等大量优化,为开发者提供了更强大的工具链。这些特性不仅提升了 C++ 代码的安全性、性能和可读性,还使得开发体验更加便捷和高效。

通过这些新特性,C++20 不仅解决了长期以来的模板编程复杂性、多线程管理等问题,还引领了现代 C++ 向更加简洁、高效的方向发展。对于 C++ 开发者来说,学习和掌握这些新特性将大大提升编程效率,并为创建更具扩展性和可维护性的代码奠定基础。

相关文章:

C++20新特性的补充讲解

C20 标志着 C 语言的一次重要更新&#xff0c;除了 Concepts、Ranges、协程等被广泛讨论的特性外&#xff0c;还有许多值得注意的改进。本文将详细探讨其他一些核心新特性&#xff0c;包括 constexpr 扩展、新增的 std::format、std::span、std::bit 操作、原子智能指针、char8…...

uni-app移动端与PC端兼容预览PDF文件

过程遇到的问题 1、如果用的是最新的版本的pdfjs的话&#xff0c;就会报Promise.withResolvers 不是一个方法的错误&#xff0c;原因是Promise.withResolvers是ES15新特性&#xff0c;想了解可参考链接&#xff0c;这里的解决方案是将插件里的涉及到Promise.withResolvers的地…...

Elman 神经网络算法详解

Elman 神经网络算法详解 一、引言 Elman 神经网络作为一种经典的递归神经网络&#xff08;RNN&#xff09;&#xff0c;在处理动态系统和时间序列数据方面具有独特的优势。它通过特殊的结构设计&#xff0c;能够有效地捕捉数据中的时间依赖关系&#xff0c;在语音识别、自然语…...

卓胜微嵌入式面试题及参考答案(2万字长文)

freeRTOS 任务是怎么调度的? 在 freeRTOS 中,任务调度主要是基于优先级的抢占式调度。每个任务都有一个优先级,系统会根据任务的优先级来决定哪个任务获得 CPU 的使用权。 当一个高优先级的任务准备运行,并且当前运行的任务优先级较低时,高优先级任务会抢占 CPU。例如,假…...

【Python】爬虫使用代理IP

1、代理池 IP 代理池可以理解为一个池子&#xff0c;里面装了很多代理IP。 池子里的IP是有生命周期的&#xff0c;它们将被定期验证&#xff0c;其中失效的将被从池子里面剔除池子里的ip是有补充渠道的&#xff0c;会有新的代理ip不断被加入池子中池子中的代理ip是可以被随机…...

金融机构-业务架构方案(高光版)

一、金融机构的设计架构 首先视角很重要,比如这样的战略视角,站得高、看得远。设计业务架构,一定要有战略高度和前瞻性。 二、什么样的架构更适合你们公司呢? 三、从架构着手,进行产品和服务创新性变革 四、具体如何设计业务架构呢?...

ubuntu内核切换network unclaimed 网卡丢失

现象一、 查网络的时候 提示只有lo network unclaimed wifi 本地局域网全部丢失 显卡丢失 解决思路 首先查看了 网卡类型 sudo lshw -C network 会显示使用的网卡 然后把这个网卡 去到realtek的官网去找驱动 驱动下下来发现debug提示 没有build目录 /libs/modules/6.8…...

【人工智能】揭秘可解释性AI(XAI):从原理到实战的终极指南

文章目录 开篇&#xff1a;AI的黑箱时代&#xff0c;你准备好揭开真相了吗&#xff1f;&#x1f50d;什么是可解释性AI&#xff08;XAI&#xff09;&#xff1f;XAI的定义XAI的分类 可解释性AI的重要性与价值建立用户信任遵循法规和伦理发现和纠正模型偏见提高模型性能促进跨领…...

小面馆叫号取餐流程 佳易王面馆米线店点餐叫号管理系统操作教程

一、概述 【软件资源文件下载在文章最后】 小面馆叫号取餐流程 佳易王面馆米线店点餐叫号管理系统操作教程 点餐软件以其实用的功能和简便的操作&#xff0c;为小型餐饮店提供了高效的点餐管理解决方案&#xff0c;提高了工作效率和服务质量 ‌点餐管理‌&#xff1a;支持电…...

图形 2.6 伽马校正

伽马校正 B站视频&#xff1a;图形 2.6 伽马校正 文章目录 伽马校正颜色空间传递函数 Gamma校正校正过程为什么需要校正&#xff1f;CRT与转换函数 为什么sRGB在Gamma 0.45空间&#xff1f; 人对亮度的敏感韦伯定律中灰值 线性工作流不在线性空间下进行渲染的问题统一到线性空…...

LLM - 计算 多模态大语言模型 的参数量(Qwen2-VL、Llama-3.1) 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/143749468 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 影响 (…...

数据可视化这样做,汇报轻松拿捏(附免费好用可视化工具推荐)

一、数据可视化的定义 数据可视化是数据分析中重要的工作之一。在完成数据采集之后&#xff0c;通过可视化方式&#xff0c;将数据转化为美观且浅显易懂的统计图/表/视频&#xff0c;从而进一步解读数据背后隐藏的价值&#xff0c;这种方数据处理方式就叫做数据可视化。近些年…...

杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权(Java版)

杂七杂八之基于JSON Web Token (JWT) 进行API认证和鉴权&#xff08;Java版&#xff09; 在现代Web应用和API开发中&#xff0c;JSON Web Token (JWT) 是一种广泛使用的认证和鉴权机制。JWT不仅简化了认证流程&#xff0c;还提供了安全的令牌传递方式&#xff0c;使得跨域认证…...

建设展示型网站企业渠道用户递达

展示型网站的主要作用便是作为企业线上门户平台、信息承载形式、拓客咨询窗口、服务/产品宣传订购、其它内容/个人形式呈现等&#xff0c;网站发展多年&#xff0c;现在依然是企业线上发展的主要工具之一且有建设的必要性。 谈及整体价格&#xff0c;自制、定制开发、SAAS系统…...

如何通过AB测试找到最适合的Yandex广告内容

想要在Yandex上找到最能吸引目标受众的广告内容&#xff0c;A/B测试是一个不可或缺的步骤。通过对比不同版本的广告&#xff0c;我们可以发现哪些元素最能引起用户的共鸣。首先&#xff0c;设计两个或多个广告版本&#xff0c;确保每个版本在标题、文案、图片等关键元素上有所不…...

AI写作(四)预训练语言模型:开启 AI 写作新时代(4/10)

一、预训练语言模型概述 ​ 预训练语言模型在自然语言处理领域占据着至关重要的地位。它以其卓越的语言理解和生成能力&#xff0c;成为众多自然语言处理任务的关键工具。 预训练语言模型的发展历程丰富而曲折。从早期的神经网络语言模型开始&#xff0c;逐渐发展到如今的大规…...

解决Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url

解决Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url 第一类情况 在anaconda创建新环境时&#xff0c;使用如下代码 conda create -n charts python3.7 错误原因&#xff1a; 默认镜像源访问速度过慢&#xff0c;会导致超时从而导致更新和下载失败。 解决方…...

员工绩效统计出现很多小数点,处理方法大全

1.直接通过数据库修改数据类型 譬如采用DECIMAL类型 2.float 降低小数点位数 3.php 采用round函数...

【启明智显分享】5G CPE为什么适合应用在连锁店中?

连锁门店需要5G CPE来满足其日益增长的网络需求&#xff0c;提升整体运营效率和竞争力。那么为什么5G CPE适合连锁店应用呢&#xff0c;小编为此做了整理&#xff0c;主要是基于以下几个方面的原因&#xff1a; 一、高效稳定的网络连接 1、高速数据传输&#xff1a; 5G CPE能…...

十大经典排序算法-希尔排序与归并排序

1、希尔排序 希尔排序&#xff0c;也称递减增量排序算法&#xff0c;是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。 希尔排序是基于插入排序的以下两点性质而提出改进方法的&#xff1a; 插入排序在对几乎已经排好序的数据操作时&#xff0c;效率高&…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...