C++17 详解 说明
# C++17 详解 说明
# 翻译说明
C++11 是 C++ 语言的一次重大更新。它带来了许多现代特性,如 lambda 表达式、常量表达式(constexpr)、可变参数模板、多线程、基于范围的for循环、智能指针等强大元素,标志着该语言取得了巨大进步。之后的 C++14 是一次较小的更新,它改进了先前标准中的一些内容,并增加了一些小特性。
虽然C++17不像C++11那样变化巨大,但它比 C++14 的改动更大,带来了许多令人激动的新增内容和改进。本书将带你逐一了解这些变化!
🛡 注意:对于现如今的 C++ 面试,你至少要掌握到 C++17 标准。
本书为《C++17 in Detail》一书的译本,首发于 cppguide.cn (opens new window)。
限于水平有限,如果您在阅读过程中有任何问题,可以联系小方(微信cppxiaofang),也欢迎加入小方的 C++技术交流群,群里面有很多C++高手,不定期发布招聘信息,加群请备注“加微信群”。
小方微信公众号【CppGuide】:
# 读者对象
本书面向所有至少具备C++11/14基础知识的C++开发者。
本书的主要目标是让你掌握C++17的实用知识。阅读本书后,你将能够超越C++11,在日常工作中运用最新的C++技术。
如果你并非C++11/14方面的专家,也无需担心。本书会提供必要的背景知识,让你在合适的语境中获取相关信息。
# 本书整体结构
C++17为语言和标准库带来了诸多变化。在本书中,所有新特性被归类为几个部分,以便于理解。
因此,本书包含以下章节:
- 第一部分——C++17语言特性
- 修正与弃用内容
- 语言澄清
- 通用语言特性
- 模板
- 代码标注
- 第二部分——C++17标准库的变化
- std::optional
- std::variant
- std::any
- std::string_view
- 字符串转换
- 文件系统
- 并行STL
- 其他变更
- 第三部分——更多示例和用例
- 使用std::optional和std::variant进行重构
- 使用[[nodiscard]]强制执行代码契约
- 用if constexpr替换enable_if
- 如何并行化CSV读取器
- 附录A——编译器支持
- 附录B——资源和链接
第一部分关于语言特性,篇幅较短,将快速带你了解最重要的变化。你可以按照自己喜欢的顺序阅读。
第二部分介绍了添加到标准库中的一组新类型和实用工具。这些辅助类型为C++代码创造了新的词汇表,比如当你使用optional、any、variant或string_view时。此外,你还拥有了新的强大功能,特别是并行算法和标准文件系统。这一部分的许多示例将结合使用C++17的其他众多特性。
第三部分整合了语言中的所有变化,并展示了综合运用许多新特性的示例。你将看到关于重构、使用新模板技术简化代码,以及使用并行STL和文件系统的讨论。虽然第一部分和第二部分也可作为单个变化的参考资料,但第三部分展示了更多结合许多特性的C++17大型应用模式。
本书的一大优势在于,对于每个新特性,你都能获取关于编译器支持和当前实现状况的信息。这样你就能查看最流行的编译器(MSVC、GCC或Clang)的特定版本是否支持该特性。本书还提供了如何在现有代码库中应用新技术的实用建议。
# 示例代码
随书配套源码下载地址:
链接: https://pan.baidu.com/s/1boC_iUa-AvPrpLsqOBZWLQ
提取码: g8cy
# 编译
要使用C++17,确保为你的编译器提供正确的标志:
- 对于GCC(至少7.1或8.0及更高版本):使用
-std=c++17
或-std=c++2a
。 - 对于Clang(至少4.0及更高版本):使用
-std=c++17
或-std=c++2a
。 - 对于MSVC(Visual Studio 2017及更高版本):在项目选项 -> C/C++ -> 语言 -> C++语言标准中,使用
/std:c++17
或/std:c++latest
。
# 格式
代码以等宽字体呈现,类似于以下示例: 对于较长且有对应cpp文件的示例:
ChapterABC/example_one.cpp
#include <iostream>
int main() {
std::string text = "Hello World";
std::cout << text << '\n';
}
2
3
4
5
6
或者是较短的代码片段(没有对应文件):
int foo() {
return std::clamp(100, 1000, 1001);
}
2
3
较长程序的代码片段通常会进行简化,仅展示核心机制。在这种情况下,你可以在随书附带的单独ZIP压缩包中找到其完整版本。
代码片段上方的标题中会提及对应的文件:Chapter ABC/example_one.cpp
通常,源代码使用带命名空间的完整类型名,如std::string
、std::clamp
、std::pmr
。然而,为了使代码紧凑且在书页上呈现美观,有时可能会省略命名空间,以节省空间。此外,为避免换行,较长的代码行可能会手动拆分为两行。在某些情况下,书中的代码可能会省略包含(include)语句 。
# 目录
- 关于本书
- 本书读者对象
- 本书整体结构
- 示例代码
# 第一部分:语言特性
- 第1章:快速入门
- 第2章:移除或修正的语言特性
- 移除的元素
- 修正内容
- 编译器支持
- 第3章:语言澄清
- 更严格的表达式求值顺序
- 保证的复制省略
- 为过度对齐数据进行动态内存分配
- 类型系统中的异常规范
- 编译器支持
- 第4章:通用语言特性
- 结构化绑定声明
- if和switch的初始化语句
- 内联变量
- 常量表达式(constexpr)lambda表达式
- 在lambda表达式中捕获[*this]
- 嵌套命名空间
- _has_include预处理表达式
- 编译器支持
- 第5章:模板
- 类模板的模板参数推导
- 折叠表达式
- if constexpr
- 用auto声明非类型模板参数
- 其他更改
- 编译器支持
- 第6章:代码标注
- 为什么需要代码标注?
- C++11之前
- C++11和C++14中的代码标注
- C++17的新增代码标注
- 章节总结
- 编译器支持
# 第二部分:标准库的变化
- 第7章:std::optional
- 引言
- std::optional的创建
- 返回std::optional
- 访问存储的值
- std::optional的操作
- 性能与内存考量
- 从boost::optional迁移
- 特殊情况:optional<bool>和optional<T*>
- std::optional的示例
- 总结
- 编译器支持
- 第8章:std::variant
- 基础
- std::variant的创建
- 修改值
- 访问存储的值
- std::variant的访问器
- std::variant的其他操作
- 异常安全保证
- 性能与内存考量
- 从boost::variant迁移
- std::variant的示例
- 总结
- 编译器支持
- 第9章:std::any
- 基础
- std::any的创建
- 修改值
- 访问存储的值
- 性能与内存考量
- 从boost::any迁移
- std::any的示例
- 总结
- 编译器支持
- 第10章:std::string_view
- 基础
- std::basic_string_view类型
- std::string_view的创建
- 其他操作
- 使用string_view的风险
- 用string_view初始化字符串成员
- 处理非空终止字符串
- 性能与内存考量
- 从boost::string_ref和boost::string_view迁移
- 示例
- 总结
- 第11章:字符串转换
- 基本字符串转换
- 从字符转换为数字:from_chars
- 从数字转换为字符:to_chars
- 基准测试
- 总结
- 编译器支持
- 第12章:搜索器与字符串匹配
- 字符串匹配算法概述
- C++17中的新算法
- 示例
- 总结
- 编译器支持
- 第13章:文件系统
- 文件系统概述
- 演示
- 路径对象
- 目录项与目录迭代
- 支持函数
- 错误处理与文件竞争
- 示例
- 章节总结
- 编译器支持
- 第14章:并行STL算法
- 引言
- 概述
- 执行策略
- 算法更新
- 新算法
- 并行算法的性能
- 示例
- 章节总结
- 编译器支持
- 第15章:库中的其他变更
- std::byte
- 对映射和集合的改进
- emplace方法的返回类型
- 采样算法
- 新的数学函数
- 共享指针和数组
- 非成员的size()、data()和empty()
- 标准库中的constexpr新增内容
- std::scoped_lock
- 多态分配器,pmr
- 编译器支持
- 第16章:移除和弃用的库特性
- 移除auto_ptr
- 移除std::random_shuffle
- 移除旧的函数式内容
- std::iterator已弃用
- 其他较小的移除或弃用项
- 编译器支持
# 第三部分:更多示例和用例
- 第17章:使用std::optional和std::variant进行重构
- 用例
- 元组版本
- 单独的结构
- 使用std::optional
- 使用std::variant
- 总结
- 第18章:使用 nodiscard 强制执行代码契约
- 引言
- 可以在哪里使用?
- 如何忽略[[nodiscard]]
- C++17之前
- 总结
- 第19章:用if constexpr替换enable_if——带可变参数的工厂
- 问题
- C++17之前
- 使用if constexpr
- 总结
- 第20章:如何并行化C++读取器
- 引言和要求
- 串行版本
- 测试
- 使用并行算法
- 总结与讨论