商品详情
书名:C++高性能编程
书号:978-7-5198-8305-8
定价:148元
作者:[瑞典]比约恩·安德里斯特(Björn Andrist),[瑞典]维克托·塞尔(Viktor Sehr)
出版时间:2024-01-15
出版社:中国电力出版社
页码: 476 字数(千字):623
开本:16开 版次:1 印次:1
品牌介绍
中国电力出版社成立于 1951 年,作为中国成立最早的中央科技出版社之一,曾隶属于水利电力部、能源部、电力工业部、国家电力公司,现为国家电网公司所属的科技出版社,在电气技术专业出版领域享有极高的声誉。该社作为以图书出版为主体,音像、电子出版物、期刊、网络出版共同发展的大型出版企业,以强大的出版资源和高素质的专业队伍,致力于向读者提供包括电力工程、电气工程、建筑工程、电子技术、信息技术、外语、大中专教材、家教等学科门类齐全的权威出版物,也竭力为广大师生提供精品教材,是教育部和北京市教委规划教材的出版基地之一。
产品特色
通过书中丰富、典型的代码示例,读者将快速把握C++的特性和编程技巧。
作者介绍
Björn Andrist是一名自由软件顾问,目前专注于音频应用程序。十多年来,他一直从事C ++的专业工作,项目范围从Unix服务器应用程序到台式机和移动设备上的实时音频应用程序,拥有KTH Royal Technology Institute的计算机工程学士学位和计算机科学硕士学位。他还教授算法和数据结构,并发编程和编程方法的课程。 Viktor Sehr是Toppluva的主要开发人员,使用针对移动硬件的高度优化的图形引擎。他在使用C ++方面拥有10年的专业经验,并专注于实时图形,音频和建筑设计,拥有Linköping大学的媒体科学硕士学位。他在Mentice和Raysearch Laboratories开发了医学可视化软件,并在Propellerhead Software开发了实时音频应用程序。
内容介绍
本书共分为14 章,包括C++概述,C++必备技能,分析和度量性能,数据结构,算法,范围和视图,内存管理,编译时编程,Utilities 基础,代理对象和惰性求值,并发,协程和惰性生成器,用协程进行异步编程和并行算法。
本书期望你具备基本的C++和计算机体系结构知识,并对提升自身专业技能真正感兴趣。希望阅读本书后,能对如何在性能和语法上改进自己的C++代码有更深入的认识。
本书适用于程序员
前言
前言
现今的C++语言为开发者提供了“编写富有表现力和健壮性代码的能力,同时几乎可在所有硬件平台上运行,并满足关键性能要求”。这使得C++成为一门独特的语言。在过去几年中,C++已经演变为一种现代化语言,使用更加有趣,并具有更实用的默认功能。
本书的目标是,为你奠定编写高效应用程序坚实的基础,并深入了解现代C++中实现库的策略。与讲述C++的历史相比,我更倾向于以实践为导向的形式介绍当前C++的运行方式,包括其组成部分以及在C++17 和C++20 中引入的特性。
考虑到C++20 中新增的特性,在编写本书时,我引入了能够与本书内容和重点相吻合的新特性。新特性更多的是关于概念的介绍,包含了少量的最佳实践和经过验证的解决方案。
在本书出版时,编译器对书中介绍的一些C++20 特性的支持仍处于试验阶段。如果在出版日期阅读,可能需要一段时间才会被编译器完全支持。
此外,本书的许多章节难度跨度较大。它们从绝对的基础知识开始,一直延伸到高级主题,如自定义内存分配器。你可以随时跳过某一节,以后再来学习。除了前三章之外,大多数章节都可以独立阅读。
我们主要的技术审校者Timur Doumler 对本书的新版本影响深远。他的热情和积极的反馈让本书第一版的部分内容得以重新修订,呈现出更彻底、更深入地讲解。C++20 的新特性自然地融入各章,Timur 也是重要的贡献者。此外,Arthur O'Dwyer、Marius Bancila 和Lewis Baker 也审校了该书的部分内容。有如此多出色的审校者们参与到这个项目中,着实是件令人高兴的事情。希望你喜欢这个新版本,就像我享受编写它一样。
本书的目标读者
本书期望读者具备基本的C++和计算机体系结构知识,并对提升自身专业技能真正感兴趣。希望阅读本书后,能对如何在性能和语法上改进自己的C++代码有更深入的认识。此外,希望你在阅读本书时,能够有一些顿悟时刻。
本书涵盖的内容
第1 章,C++概述,介绍了C++的重要特性,如零成本抽象、值语义、常量正确性、显式所有权和错误处理。同时,本章还探讨了C++的缺点。
第2 章,C++必备技能,描述了使用auto 进行自动类型推导、lambda 函数、move 语义和错误处理。
第3 章,分析和度量性能,将教你如何使用大O 符号来分析算法的复杂度,以及如何对代码进行剖析以找到性能瓶颈,并介绍了使用Google Benchmark 进行性能测试的方法。
第4 章,数据结构,阐述了构建高效数据结构的重要性,以便快速访问数据。同时介绍了标准库中的容器,如std::vector,std::list、std::unordered_map 和std::priority_queue。本章最后还演示了如何使用并行数组。
第5 章,算法,介绍了标准库中最重要的算法。将学习如何使用迭代器(Iterator)和范围(Ranges)处理数据,以及如何实现自己的通用算法。
第6 章,范围和视图,将学习如何使用C++20 中引入的Ranges 库来组织算法,以及Ranges 库视图的实用性以及惰性求值的好处。
第7 章,内存管理,重点关注安全而高效的内存管理。内容包括内存所有权、RAII、智能指针、堆栈内存、动态内存和自定义内存分配器。
第8 章,编译时编程,介绍使用constexpr、consteval 和类型萃取等元编程技术。你将学习如何利用C++20 的概念和Concepts 库,以及元编程的实际应用,如反射。
第9 章,Utilities 基础,引导你了解Utilities 库,如何利用编程技术从std::optional、std::any和std::variant 等类型中受益。
第10 章,代理对象和惰性求值,探讨如何在保留清晰语法的同时,使用代理对象对内部优化,以及操作符重载的一些创造性用法。
第11 章,并发,涵盖并发编程的基础知识,包括并行执行、共享内存、数据竞争和死锁。介绍了C++线程支持库、Atomic 库和C++内存模型。
第12 章,协程和惰性生成器,提供对协程抽象的综合介绍。你将学习如何在CPU 上执行普通函数和协程,以及C++20 的无栈协程和生成器的用法。
第13 章,用协程进行异步编程,介绍使用C++20 的无栈协程进行并发编程,并讨论使用Boost.Asio 进行异步网络编程的话题。
第14 章,并行算法,展示编写并行算法的复杂度及如何度量其性能,以及如何利用标准库算法和执行策略在并行环境中进行并行计算。
阅读本书的必要准备
为了从本书中获得最大的收益,你确实需要具备基本的C++知识。如果你已经遇到与性能相关的问题,并正在寻找新的工具和实践方法来优化性能,那么你将能够更好地理解和应用本书中的内容,并从中获得更大的收获。
本书包含大量代码示例,其中一些来自真实项目,但大多数是经过改造或大幅简化的示例,用于说明概念,并不会直接提供可在生产环境中运行的代码。
我已经按照章节将所有代码示例划分并放置在相应的源文件中,这样做可以方便快速地找到实验案例。此外,我还使用了Google Test 框架编写了自动化测试用例,以取代示例中的大部分main()函数。我希望这些改变对你有所帮助,而不会增加困惑。这样做有助于我为每个例子提供有意义的描述,并使大家能够更便捷地一次性运行每章中的所有例子。
为了编译和运行这些示例,你将需要:
● 一台电脑。
● 操作系统(这些示例已经在Windows、Linux 和macOS 上得到了验证)。
● 编译器(我使用的是Clang、GCC 和Microsoft Visual C++)。
● CMake。
提供的示例代码中的CMake 脚本将下载并安装其他依赖项,如Boost、Google Benchmark和Google Test。
在撰写本书的过程中,我发现使用Compiler Explorer(https://godbolt.org/)非常有帮助。
它是一个在线编译器,可以在此尝试不同版本的编译器。如果你尚未尝试过这些工具,我强烈建议你去体验一下!它们将为你带来许多便利和优势。
下载示例代码文件
本书代码托管在GitHub 上,位于https://github.com/ PacktPublishing/Cpp-High-Performance-Second-Edition。代码会在现有GitHub 代码库中持续更新。
你可在https://github.com/PacktPublishing/找到其他由Packt 出版社出版的书籍和视频中的代码。
下载彩色插图
本书还提供了一个包含本书中使用的屏幕截图和图表的彩色图片的PDF 文件。可在这里下载该文件:https://static.packt-cdn.com/ downloads/9781839216541_ColorImages.pdf。
文本格式约定
本书使用以下文本约定。
CodeInText:表示文本、文件夹名称、文件名、文件扩展名、假的URL 和用户输入。如:
“关键字constexpr 是在C++11 中引入的。”
以下是代码块的约定:
#include
目录
目录
序
前言
第1 章 C++概述 1
11 为什么是C++ 1
111 零成本抽象 1
112 可移植性 4
12 与其他语言对比 4
121 竞争语言和性能 5
122 与性能无关的C++语言特性 7
123 C++的局限性 12
13 本书使用的库和编译器 13
14 总结 13
第2 章 C++必备技能 14
21 用auto 关键字进行自动类型推断 14
211 在函数签名中使用auto 14
212 对变量使用auto 16
213 指针的常量传播 18
22 移动语义 19
221 拷贝构造函数,交换与移动 20
222 资源获取与五法则 22
223 具名变量和右值 25
224 默认移动语义和零法则 27
225 将&&修饰符应用于类成员函数32
226 当拷贝被省略时,无论如何都不要移动 32
227 适时使用值传递 33
23 设计带有错误处理的接口 35
231 契约 36
232 错误处理 39
24 函数对象和lambda 表达式 46
241 C++lambda 的基本语法 46
242 捕获子句 47
243 为lambda 表达式分配C 函数指针 53
244 Lambda 类型 54
245 lambda 表达式和std::function 54
246 泛型lambda 58
25 总结 60
第3 章 分析和度量性能 61
31 渐进复杂度和大O 符号 61
311 增长率 66
312 均摊时间复杂度 67
32 度量什么?该如何度量? 69
321 性能特征 71
322 运行时间的提升 71
323 性能计数器 72
324 最佳实践:性能测试 73
33 了解代码和热点 74
331 插桩型剖析器 75
332 采样型剖析器 77
34 微基准测试 79
341 阿姆达尔定律 80
342 微基准测试的隐患 81
343 微基准测试实例 81
35 总结 87
第4 章 数据结构 88
41 计算机内存的特性 88
42 标准库容器 92
421 序列式容器 92
422 关联式容器 96
423 容器适配器100
43 使用视图 103
44 性能方面的考量 106
441 在复杂度与开销间寻求平衡 106
442 了解并使用适当的API 函数 107
45 并行数组 108
46 总结 115
第5 章 算法 116
51 标准库算法概述 116
511 标准库算法的演进 116
512 解决日常问题 117
52 迭代器与范围 124
521 迭代器 124
522 哨兵值与pasttheend 迭代器 125
523 范围 126
524 迭代器类别 127
53 标准算法的特点 129
54 算法不会改变容器大小 129
541 有输出的算法需要自己分配数据 130
542 算法默认使用operator==()和operator<() 131
543 使用projection 的约束算法 132
544 算法要求move 不能抛出异常 133
545 算法具有复杂度保证 133
546 算法的性能与C 语言库中的等价函数一样好 134
55 编写和使用泛型算法 135
551 非泛型算法 135
552 泛型算法 136
553 可被泛型算法使用的数据结构 137
56 最佳实践 139
561 使用约束算法 139
562 只对需要检索的数据进行排序 139
563 使用标准算法而非原始for 循环 142
564 避免容器拷贝 148
57 总结 149
第6 章 范围和视图 150
61 Ranges 库的动机 150
62 理解Ranges 库中的视图 153
621 视图是可组合的154
622 范围视图带有范围适配器155
623 视图是具有复杂度保证的非具权范围156
624 视图不改变底层容器157
625 视图可以被具体化为容器157
626 视图是惰性求值的158
63 标准库中的视图 160
631 范围视图160
632 生成视图160
633 转换视图160
634 再谈std::string_view 与std::span 162
64 Ranges 库的未来 164
65 总结 164
第7 章 内存管理 165
71 计算机内存 165
711 虚拟地址空间165
712 内存页166
713 抖动167
72 进程内存 167
721 栈内存168
722 堆内存171
73 内存中的对象 172
731 创建与销毁对象172
732 内存对齐176
733 内存补齐179
74 内存所有权 182
741 隐式处理资源183
742 容器185
743 智能指针185
75 小对象优化 188
76 自定义内存管理 191
761 创建arena 192
762 自定义内存分配器 196
763 使用多态内存分配器 201
764 实现自定义内存资源 205
77 总结 207
第8 章 编译时编程 208
81 模板元编程介绍 208
82 创建模板 209
83 使用整数作为模板参数 211
84 提供模板的特化 212
85 编译器如何处理模板函数 212
86 缩写函数模板 213
87 使用decltype 接收变量类型 214
88 类型萃取 215
881 类型萃取的类别 215
882 类型萃取的使用 216
89 常量表达式的使用 217
891 运行时环境中的constexpr 函数 218
892 使用consteval 声明即时函数 219
893 编译时多态与运行时多态 222
894 示例:使用if constexpr 的泛型取模函数 223
810 编译时检查程序错误 224
8101 利用assert 在运行时触发错误 224
8102 利用static_assert 在编译时触发错误 225
811 约束与概念 226
8111 Point2D 模板,无约束版 226
8112 泛型接口与不友好的报错信息 227
8113 约束和概念的语法 229
8114 标准库中的概念 234
812 元编程实例 235
8121 示例1:创建通用的安全强制转换函数 235
8122 示例2:在编译时对字符串进行哈希处理 238
813 总结 245
第9 章 Utilities 基础 246
91 用std::optional 表示可选值· 246
911 可选的返回值247
912 可选的成员变量248
913 避免在枚举中使用空状态248
914 std::optional 的排序与比较 249
92 固定大小的异质集合 250
921 std::pair 250
922 std::tuple 251
923 访问元组中的成员252
924 遍历std::tuple 的元素253
925 元组展开254
926 为元组实现其他算法255
927 元组元素访问256
928 结构化绑定257
93 可变参数模板 258
94 可动态调整大小的异质集合 261
941 std::variant 262
942 std::variant 的异常安全性 264
943 访问variant265
95 使用了variant 的异质集合 266
951 访问variant 容器中的值 267
952 全局函数std::get() 268
96 实际案例 269
961 示例1:投影与比较运算符 269
962 示例2:反射 270
97 总结 273
第10 章 代理对象和惰性求值 274
101 惰性求值和代理对象简介· 274
1011 惰性求值与急切计值 274
1012 代理对象 275
102 避免使用代理对象构建对象 276
1021 使用代理比较连接的字符串 276
1022 实现代理 277
1023 右值修饰符 278
1024 存储拼接好的代理对象 279
1025 性能评估 279
103 延迟sqrt 计算 280
1031 一个简单的二维向量类 280
1032 示例背后的数学概念 281
1033 实现LengthProxy 283
1034 用LengthProxy 比较长度 285
1035 用LengthProxy 计算长度 286
1036 性能评估 287
104 探索运算符重载和代理对象 289
105 总结 291
第11 章 并发 292
111 了解并发的基本概念 292
112 是什么让并发编程变得困难? 293
113 并发和并行 293
1131 时间切片 294
1132 共享内存 295
1133 数据竞争 296
1134 互斥锁 298
1135 死锁 299
1136 同步任务与异步任务 299
114 C++中的并发编程 300
1141 线程支持库 301
1142 C++20 中其他的同步原语 315
1143 C++中的原子操作 326
1144 C++内存模型 335
115 无锁编程 339
116 性能指南 341
1161 避免竞争 341
1162 避免阻塞操作 342
1163 线程/CPU 核数342
1164 线程优先级 343
1165 线程亲和性 343
1166 伪共享 344
117 总结 345
第12 章 协程和惰性生成器 346
121 几个引人入胜的例子 347
122 协程抽象 348
1221 子例程和协程 349
1222 在CPU 上运行子例程和协程 350
1223 无栈协程和有栈协程 358
1224 目前为止所学的内容 360
123 C++中的协程 360
1231 标准C++中协程的涵盖内容 361
1232 C++函数成为协程的关键是什么?361
1233 一个最简但完整的示例 363
1234 分配协程状态 368
1235 避免悬空引用 370
1236 错误处理 375
1237 自定义点 375
124 生成器 376
1241 实现生成器 376
1242 使用Generator 类380
1243 在实际工作中使用生成器 387
125 性能 395
126 总结 395
第13 章 用协程进行异步编程 396
131 再谈可等待类型 396
132 实现一个基本任务类型 398
1321 处理返回值和异常 401
1322 恢复等待中的协程 402
1323 支持void Task 404
1324 同步等待任务完成 406
1325 使用sync_wait()测试异步任务 411
133 封装基于回调的API 412
134 使用BoostAsio 实现的并发服务器 416
1341 实现服务器 416
1342 运行并连接服务器 418
1343 在服务器示例中实现的(以及未实现的)功能 419
135 总结 420
第14 章 并行算法 421
141 并行的重要性 421
142 并行算法 421
1421 度量并行算法 422
1422 回顾阿姆达尔定律 423
1423 实现并行std::transform() 424
1424 并行化std::count_if() 434
1425 并行化std::copy_if() 435
143 标准库中的并行算法 441
1431 执行策略 442
1432 异常处理 446
1433 并行算法的新增和修改 447
1434 并行化基于索引的for 循环 449
144 在GPU 上执行算法 450
145 总结 451
146 分享经验 452
- 有电书房
- 扫描二维码,访问我们的微信店铺