Skip to content

Commit ef39f61

Browse files
committed
2021-12-01 23:11:18
1 parent 0576fd5 commit ef39f61

File tree

15 files changed

+185
-213
lines changed

15 files changed

+185
-213
lines changed

trans/cpp-hiperf/00.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 前言
1+
# 零、前言
22

33
今天的 C++ 为程序员提供了编写富于表现力和健壮的代码的能力,同时仍然可以针对几乎任何硬件平台,同时满足性能关键的要求。这使得 C++ 成为一种独特的语言。在过去的几年里,C++ 已经变成了一种现代语言,使用起来更有趣,并且有更好的默认值。
44

@@ -28,19 +28,19 @@
2828

2929
*第五章**算法*,介绍了标准库中最重要的算法。您还将学习如何使用迭代器和范围,以及如何实现自己的通用算法。
3030

31-
*第 6 章**范围和视图*,将教你如何使用 C++ 20 中引入的范围库编写算法。您将了解为什么范围库中的视图是有用的,以及惰性评估的一些好处
31+
*第 6 章**范围和视图*,将教你如何使用 C++ 20 中引入的范围库编写算法。您将了解为什么范围库中的视图是有用的,以及延迟求值的一些好处
3232

3333
*第 7 章**内存管理*,重点介绍安全高效的内存管理。这包括内存所有权、RAII、智能指针、堆栈内存、动态内存和自定义内存分配器。
3434

3535
*第 8 章**编译时编程*,解释了使用`constexpr``consteval`和类型特征的元编程技术。您还将学习如何使用 C++ 20 概念和新概念库。最后,它提供了元编程用例的实际例子,例如反射。
3636

3737
*第 9 章**基本实用程序*将指导您浏览实用程序库,以及如何使用编译时编程技术从诸如`std::optional``std::any``std::variant`等类型中受益。
3838

39-
*第 10 章**代理对象和惰性评估*探讨了如何使用代理对象来执行幕后优化,同时保持干净的语法。此外,还演示了运算符重载的一些创造性用法。
39+
*第 10 章**代理对象和延迟求值*探讨了如何使用代理对象来执行幕后优化,同时保持干净的语法。此外,还演示了运算符重载的一些创造性用法。
4040

4141
*第 11 章**并发*,涵盖了并发编程的基础,包括并行执行、共享内存、数据竞争和死锁。它还包括对 C++ 线程支持库、原子库和 C++ 内存模型的介绍。
4242

43-
*第 12 章**协同程序和懒惰生成器*,包含协同程序抽象的一般介绍。您将了解如何使用堆栈和堆在中央处理器上执行普通函数和协同程序。介绍了 C++ 20 无堆栈协同程序,您将发现如何使用生成器解决问题。
43+
*第 12 章**协程和延迟生成器*,包含协程抽象的一般介绍。您将了解如何使用堆栈和堆在中央处理器上执行普通函数和协程。介绍了 C++ 20 无堆栈协程,您将发现如何使用生成器解决问题。
4444

4545
*第 13 章**用 coroutines 进行异步编程*,介绍了 C++ 20 中使用无堆栈 Coroutines 进行并发编程,并涉及到使用 Boost.Asio 进行异步网络编程的主题
4646

trans/cpp-hiperf/01.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# one
2-
3-
# C++ 简介
1+
# 一、C++ 简介
42

53
这本书旨在为您提供编写高效应用的坚实基础,以及在现代 C++ 中实现库的策略。我试图用一种实用的方法来解释今天 C++ 是如何工作的,从 C++ 11 到 C++ 20 的现代特性是语言的自然组成部分,而不是从历史上来看 C++。
64

trans/cpp-hiperf/02.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# Two
2-
3-
# 基本的 C++ 技术
1+
# 二、基本的 C++ 技术
42

53
在这一章中,我们将深入研究一些基本的 C++ 技术,例如移动语义、错误处理和 lambda 表达式,这些将在本书中用到。这些概念中的一些仍然让有经验的 C++ 程序员感到困惑,因此我们将研究他们的用例以及他们是如何工作的。
64

trans/cpp-hiperf/03.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# three
2-
3-
# 分析和测量性能
1+
# 三、分析和测量性能
42

53
由于这是一本关于编写高效运行的 C++ 代码的书,我们需要涵盖一些关于如何衡量软件性能和评估算法效率的基础知识。本章中的大多数主题都不是针对 C++ 的,只要遇到性能问题,就可以使用。
64

trans/cpp-hiperf/04.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# four
2-
3-
# 数据结构
1+
# 四、数据结构
42

53
在最后一章中,我们讨论了如何分析时间和内存复杂性以及如何衡量性能。在本章中,我们将讨论如何从标准库中选择和使用数据结构。为了理解为什么某些数据结构在今天的计算机上工作得非常好,我们首先需要介绍一些关于计算机内存的基础知识。在本章中,您将了解:
64

trans/cpp-hiperf/05.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# five
2-
3-
# 算法
1+
# 五、算法
42

53
C++ 程序员广泛使用标准库中的容器。例如,很少找到没有引用`std::vector``std::string`的 C++ 代码库。然而,根据我的经验,标准库算法的使用频率要低得多,尽管它们提供了与容器相同的好处:
64

trans/cpp-hiperf/06.md

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
# six
1+
# 六、范围和视图
22

3-
# 范围和视图
4-
5-
本章将从上一章关于算法及其局限性的地方继续。范围库中的视图是算法库的强大补充,它允许我们在一系列元素上将多个转换组合成一个惰性的评估视图。阅读本章后,您将了解什么是范围视图,以及如何将它们与标准库中的容器、迭代器和算法结合使用。
3+
本章将从上一章关于算法及其局限性的地方继续。范围库中的视图是算法库的强大补充,它允许我们在一系列元素上将多个转换组合成一个延迟的评估视图。阅读本章后,您将了解什么是范围视图,以及如何将它们与标准库中的容器、迭代器和算法结合使用。
64

75
具体来说,我们将涵盖以下主要主题:
86

@@ -84,7 +82,7 @@ auto get_max_score(const std::vector<Student>& students, int year) {
8482
8583
虽然这在这个小例子中很容易实现,但我们希望能够通过组成小的算法构建块来实现这个算法,而不是使用单个`for`循环从头开始实现它。
8684
87-
我们想要的是像使用算法一样可读的语法,但是能够避免为算法中的每一步构建新的容器。这就是范围库中的视图发挥作用的地方。虽然范围库包含的不仅仅是视图,但与算法库的主要区别是能够将本质上是不同类型的迭代器组成一个惰性的求值范围
85+
我们想要的是像使用算法一样可读的语法,但是能够避免为算法中的每一步构建新的容器。这就是范围库中的视图发挥作用的地方。虽然范围库包含的不仅仅是视图,但与算法库的主要区别是能够将本质上是不同类型的迭代器组成一个延迟的求值范围
8886
8987
如果前面的示例是使用范围库中的视图编写的,那么它会是这样的:
9088
@@ -121,7 +119,7 @@ for (auto s : squared_view) { // The square lambda is invoked here
121119
// Output: 1 4 9 16
122120
```
123121

124-
变量`squared_view`不是数值平方的`numbers`向量的副本;它是数字的代理对象,只有一个细微的区别——每次你访问一个元素时,都会调用`std::transform()`函数。这就是为什么我们说一个视图是懒惰评估的
122+
变量`squared_view`不是数值平方的`numbers`向量的副本;它是数字的代理对象,只有一个细微的区别——每次你访问一个元素时,都会调用`std::transform()`函数。这就是为什么我们说一个视图是延迟求值的
125123

126124
从外部来看,您仍然可以像任何常规容器一样迭代`squared_view`,因此,您可以执行常规算法,如`find()``count()`,但是,在内部,您没有创建另一个容器。
127125

@@ -198,7 +196,7 @@ auto scores =
198196
199197
## 范围视图配有范围适配器
200198
201-
正如您之前看到的,Ranges 库还允许我们使用范围适配器和管道操作符来构建视图,以获得更优雅的语法(您将在*第 10 章*、*代理对象和惰性评估*中了解更多关于在自己的代码中使用管道操作符的信息)。前面的代码示例可以通过使用 range adaptor 对象来重写,我们将得到如下内容:
199+
正如您之前看到的,Ranges 库还允许我们使用范围适配器和管道操作符来构建视图,以获得更优雅的语法(您将在*第 10 章*、*代理对象和延迟求值*中了解更多关于在自己的代码中使用管道操作符的信息)。前面的代码示例可以通过使用 range adaptor 对象来重写,我们将得到如下内容:
202200
203201
```cpp
204202
using namespace std::views; // range adaptors live in std::views
@@ -293,13 +291,13 @@ auto strings = to_vector(r);
293291
// strings is now a std::vector<std::string>
294292
```
295293

296-
请记住,一旦视图被复制回容器,原始容器和转换后的容器之间就不再有任何依赖关系。这也意味着物化是一个急切的操作,而所有的视图操作都是懒惰的
294+
请记住,一旦视图被复制回容器,原始容器和转换后的容器之间就不再有任何依赖关系。这也意味着物化是一个急切的操作,而所有的视图操作都是延迟的
297295

298296
## 视图被偷懒评估
299297

300298
由视图执行的所有工作都懒洋洋地发生。这与`<algorithm>`头中的函数相反,这些函数在被调用时会立即对所有元素执行工作。
301299

302-
你已经看到`std::views::filter`视图可以代替`std::copy_if()`算法,`std::views::transform`视图可以代替`std::transform()`算法。当我们使用视图作为构建块并将它们链接在一起时,通过避免急切算法所需的容器元素的不必要的副本,我们从惰性评估中受益
300+
你已经看到`std::views::filter`视图可以代替`std::copy_if()`算法,`std::views::transform`视图可以代替`std::transform()`算法。当我们使用视图作为构建块并将它们链接在一起时,通过避免急切算法所需的容器元素的不必要的副本,我们从延迟求值中受益
303301

304302
但是`std::sort()`呢?有相应的排序视图吗?答案是否定的,因为它需要视图首先急切地收集所有元素,以便找到要返回的第一个元素。相反,我们必须通过在我们的视图上明确地调用 sort 来实现这一点。在大多数情况下,我们还需要在排序之前物化视图。我们可以用一个例子来澄清这一点。假设我们有一个被谓词过滤的数字向量,如下所示:
305303

@@ -323,7 +321,7 @@ std::ranges::sort(v);
323321
// v is now 1, 1, 5, 7
324322
```
325323
326-
但是为什么有这个必要呢?答案是这是懒惰评价的结果。当评估需要通过一次读取一个元素来偷懒时,过滤器视图(和许多其他视图)不能保留底层范围的迭代器类型(在本例中为`std::vector`)。
324+
但是为什么有这个必要呢?答案是这是延迟评价的结果。当评估需要通过一次读取一个元素来偷懒时,过滤器视图(和许多其他视图)不能保留底层范围的迭代器类型(在本例中为`std::vector`)。
327325
328326
那么,有没有可以排序的视图呢?是的,一个例子是`std::views::take`,它返回一个范围内的第一个 *n* 元素。以下示例编译并运行良好,无需在排序前具体化视图:
329327
@@ -486,7 +484,7 @@ auto split(std::string_view s, char delim) {
486484

487485
在 C++ 20 中被接受的 Ranges 库是基于 Eric Niebler 创作的一个库,可在[https://github.com/ericniebler/range-v3](https://github.com/ericniebler/range-v3)获得。目前,这个库的组件中只有一小部分进入了标准,但很可能很快会添加更多的东西。
488486

489-
除了许多尚未被接受的有用视图,如`group_by``zip``slice``unique`之外,还有**动作**的概念,可以像视图一样管道化。然而,行动不是像视图一样被懒惰地评估,而是执行范围的急切突变。排序是一个典型动作的例子。
487+
除了许多尚未被接受的有用视图,如`group_by``zip``slice``unique`之外,还有**动作**的概念,可以像视图一样管道化。然而,行动不是像视图一样被延迟地评估,而是执行范围的急切突变。排序是一个典型动作的例子。
490488

491489
如果您等不及将这些功能添加到标准库中,我建议您看一看 range-v3 库。
492490

trans/cpp-hiperf/07.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# seven
2-
3-
# 内存管理
1+
# 七、内存管理
42

53
读完前面几章,我们处理内存的方式会对性能产生巨大影响,这应该不再令人惊讶。中央处理器花费大量时间在中央处理器寄存器和主存储器之间洗牌(向主存储器加载数据和从主存储器存储数据)。如*第四章**数据结构*所示,CPU 使用内存缓存来加速对内存的访问,程序需要缓存友好才能快速运行。
64

trans/cpp-hiperf/08.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# eight
2-
3-
# 编译时编程
1+
# 八、编译时编程
42

53
C++ 能够在编译时计算表达式,这意味着程序执行时已经计算出了值。尽管自 C++ 98 以来元编程已经成为可能,但由于其复杂的基于模板的语法,它最初非常复杂。随着`constexpr``if constexpr`以及最近的 C++ *概念*的引入,元编程变得更加类似于编写常规代码。
64

trans/cpp-hiperf/09.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# nine
2-
3-
# 基本公用事业
1+
# 九、基本工具
42

53
本章将介绍 C++ 实用程序库中的一些基本类。为了有效地处理包含不同类型元素的集合,将使用前一章中介绍的一些元编程技术。
64

0 commit comments

Comments
 (0)