猜你喜欢
深度探索C++14

深度探索C++14

书籍作者:[德] Peter ISBN:9787121354984
书籍语言:简体中文 连载状态:全集
电子书格式:pdf,txt,epub,mobi,azw3 下载次数:6976
创建日期:2021-02-14 发布日期:2021-02-14
运行环境:PC/Windows/Linux/Mac/IOS/iPhone/iPad/Kindle/Android/安卓/平板
内容简介

本书从传统的Hello World开始,先介绍了语言入门C++所必须的基本要素(如表达式、语句、声明);再到和程序组织有关的函数、类;然后深入探讨了C++所支持的泛型编程、元编程和面向对象等不同编程范式,并且提供了很多的例子可以让读者仔细体会它们之间的联系、区别和适用场景;最后再以一个中型项目为例介绍了一些大型工程所必备的基础知识。本书适合C++初学者、正在开发和维护科学和工程软件的软件工程师,以及希望学习和理解现代C++机制如泛型编程和元编程的读者。

作者简介

Peter Gottschling 热衷于编写前沿的科学计算软件,他希望他的热情也能感染读者。因为职业的缘故他编写了MTL4(矩阵模板库4),同时也是Boost Graph Library 的作者之一。他曾在多个C++ 课程和专业培训中分享过开发经验,并撰写了本书。
译者吴野,线上常用ID“空明流转”。毕业后在数家IT企业工作过,拥有数年软件开发和硬件设计经验。C++为其常用编程语言之一,业余时间也会阅读一些C++标准和标准提案。

编辑推荐
适读人群 :编程人员

如今科学工程项目越来越大、越来越复杂,许多项目都采用C++来完成。同时,随着嵌入式硬件的日益强大,嵌入式软件编程语言也转向C++。从嵌入式硬件到高级编程抽象,C++几乎支持每个层级的编程。总而言之,C++是一门每一个技术人员都需要了解的语言。
本书深入介绍了基于C++高级功能的复杂方法。作者选用了多个不同领域的案例,同时结合了向物理学、数学和工程学等专业学生教授C++的丰富经验,来介绍C++中的关键概念。
本书旨在帮助你快速入门,也会让你掌握从lambda表达式到模板表达式的诸多高阶功能。 你还将学习如何使用C++强大的程序库:标准模板库(STL)和用于算法、线性代数、微分方程、图形的科学类库。
作者演示了如何使用面向对象、泛型、元编程和过程式编程来编写清晰明了、直观练达的软件。当你学完本书,你将掌握如何使用C++来编写高质量、高性能的软件。

前言

推荐序1:一些关于C++的大实话
我在北美这几年面试了上百位应聘者,这边的公司大多会让应聘者自选编程语言。我注意到一个现象,即使用C++作为面试语言的应聘者比例很低,大约不到1/10,在应届生中这个比例更低,远远不如我早前在上海和香港那几年面试的情况。在面试中,我也不再考察C++语法和标准库的知识点了。因为据我了解,即便是北美计算机科班出身的应届生也不一定在学校学过C++,他们学习的编程语言一般以Java或Python为主,然后因为操作系统或体系结构课程需要,会学一点C语言。这些新人参加工作之后,如果项目需要,会用两三周的时间,在原有的编程语言基础上快速入门C++,然后仿照项目现有代码的风格和习惯,开始上手C++编程。这种学习方式的优点是主次分明、重点突出、有的放矢。相比之下,其他专业的毕业生掌握C++的比例就更低了,我见过一些统计或者信号处理方向的博士们毕业之后进入工业界,需要把自己原来用R语言或者MATLAB实现的模型或算法用C++重写,使之融入公司的产品。正是因为有这样的开发者使用C++来完成工作中的开发任务,才赋予了这门语言蓬勃的生命力,否则它就只能沦为C++语言爱好者的玩物了。
换句话说,早前我刚参加工作那会儿的行情是:在学校学好C++,借此找到好工作。现在的情况变成了先学会编程,找份好工作,如果工作需要,再去学C++。本书正是适应这种“新需求”的产物,作者Peter Gottschling在科学计算领域颇有建树,也有丰富的教学经验,他的书抓住了重点,能够把C++常用功能的使用方法快速传授给读者。
其实,大多数普通程序员,包括我自己,在工作中很少有自由选择语言的权利。我在Morgan Stanley利用C++写了几年的实时外汇交易系统,后来在Google用C++写了几年的广告后台服务。并不是因为我擅长C++才决定在工作中采用C++,而是因为这些系统本来就是以C++为主的,我参与到其中,自然也得用C++来开发。话说回来,对于目前很多技术热点(Web和移动开发、机器学习)来说,C++并不是一门必须要学习和掌握的语言,很多不懂C++的程序员也能拥有相当辉煌的职业生涯。因此,对于C++初学者,与其问C++能做什么,不如多想想你需要用C++做什么。你想加入的公司或开发组是不是主要使用C++来开发项目?如果是,你掌握的C++知识是否足以胜任此项工作?
那么,C++要学到什么程度?其实项目越大,参与的人越多,使用的技术就会越趋于“平凡”,毕竟要照顾大家的平均水平,不宜剑走偏锋。对于多人开发的大中型项目,我认为大多数组员把C++学到能读懂并仿写LevelDB源码的程度,就足以应付日常的开发。只有那些写C++模板库给别人用的少数人,才需要钻研比较高深的模板(元)编程技术。举个例子,用逗号分隔字符串大家都会写,但是实现absl::StrSplit()用到的语法就不是每个C++程序员都需要掌握的。
商业公司使用C++开发商业项目,一定有其充分理由。常见的理由有两个:节约成本、增加收入。节约成本,一般认为是节约机器(服务器)的成本。虽然大家都知道人比机器贵,但是当系统的规模大到一定程度(5万台以上可称为Warehouse-Scale Computers )时,节约10%的机器资源所能获得的收益就不容忽视了。 在竞争环境下,一个高效的系统有可能增加收入。例如,在实时在线广告竞价领域,用C++能在规定的期限(比如100ms)内对候选广告做更细致的评分,从中挑选出更有机会被用户点击的广告。对于在线广告公司来说,提升广告的点击率是能直接影响企业利润的核心需求,那么用C++来实现广告系统似乎是一个很自然的选择。
大家普遍认为,C++是一门高效的(efficient)语言,高效通常指的是节省机器资源,但高效不等于高性能(high performance)。随着摩尔定律的终结,目前高性能领域往往会使用特定硬件加速(Domain-Specific Architecture,DSA)。如果计算密集型的代码,要么用SIMD指令做向量化,要么放到GPU上去做并行计算,这样获得的性能提升通常会远超更换编程语言的效果。用C/C++实现的AES加密算法再怎么优化,也比不过在CPU里加几条相关的指令。Google为了提高机器学习的效率,还专门研发了TPU加速芯片。 “用C++写出来的程序一定是高性能的”这种观点如今看来不免有些太天真了。
C++好用不好用,主要看你的工具和库好不好。我没见过哪个公司只用C++标准库做开发,因为标准库提供的功能实在是太少了,而且标准库提供的不一定是最好的选择。Google前不久开源了自己用的C++基础库Abseil,我尤其推荐其中的两个:
?? 号称瑞士军刀的散列表,用于替换标准库中的unordered_set/unordered_map。得益于memory locality,absl::flat_hash_map的性能显著高于std::unordered_map。
?? 时间库,用于替换标准库中的std::chrono。
与10年前相比,C++的代码工具有了巨大的进步,这主要得益于LLVM/Clang为编写C++源码工具提供了坚实而便利的基础,让工具对C++代码的理解从正则表达式层面提升到了抽象语法树层面,从而能真正理解一段C++代码的语意。Clang-Tidy让稍具水平的程序员也能方便地编写工具来改进codebase的质量。 此外,新的运行时工具也有助于在测试阶段发现错误。
俗话说,到什么山头唱什么歌,在一个公司中多人合作编写代码时要遵循统一的约定,不能随心所欲地自由发挥。这里列出几个工业级的C++编码规范,它们各自都被上百万行的海量代码遵循着,可供大家借鉴并体会哪些知识点是反复强调、需要下功夫去好好掌握的:
?? Google C++ Style Guide/C++ Tips of the Week
?? LLVM Coding Standards
?? Qt Coding Conventions
值得一提的是,目前这几个规范都明确地禁用异常,因此我认为不必为C++异常投入过多的学习精力,将来的工作中很可能用不到。在工作中,对于可能返回错误的函数,我们一般的做法是返回Status或者StatusOr
最后,提一点建议:写一个新的类时,绝大多数情况下,请先禁用复制构造函数和赋值操作符,这将有效地防止浅复制导致的内存错误。
我期待将来有一天C++标准能采纳一个建议:把复制构造函数和赋值操作符默认删除(=delete),除非用户显式地定义它们。祝大家学习愉快!
陈 硕 美国·加利福尼亚州 2019年7月

推荐序2
C++是一门强大的语言,而C++本身也在不断演进中,最新的标准已经演进到C++20,并引入了相当多引人注目的特性,如Concept、Module和Coroutine。相比C++20,本书着眼的C++11/14是对编译器支持相对成熟,并且工业项目也愿意采用的C++新标准。C++11/14相比C++98/03也具有非常多的新特性,如auto、匿名函数、constexpr、move语义等。本书从丰富的代码例子出发,引出C++11/14新特性要解决的问题,避免了过多的语言特性描述,这样可以很直观地让大家知道某个特性实际是要怎么使用的。但是,本书的不足之处在于有点发散,很多概念一笔带过。总体而言,瑕不掩瑜,本书对于已有C++98/03基础,且想要快速补足C++11/14知识的人群来说是一本合适的图书。
吴 钊(蓝色)

前言
世界是建立在C++(以及它的C子集)上的。
——Herb Sutter
Google、Amazon和Facebook的很多基础设施都构建于C++之上。还有相当一部分的其他底层技术也是使用C++实现的。在电信领域,几乎所有的固定电话和手机都由C++开发的软件所驱动。在德国,几乎所有的主要通信节点都是由C++处理的,这意味着作者的家庭也是C++的间接受益者。
即便是用其他语言编写的软件也可能会依赖于C++,因为最流行的编译器都是用C++实现的:比如Visual Studio、Clang,以及GNU和Intel编译器中较新的组件。 在Windows系统上运行的组件更是如此,因为Windows系统(以及Office)本身就是用C++开发的。C++无所不在,甚至你的手机和汽车,都一定包含了用C++开发的组件。C++的发明者Bjarne Stroustrup制作了一个示例网页,上述大部分例子都源于该网页。
科学和工程领域的许多高质量软件包也都是用C++实现的。当项目超过一定规模,且数据结构相当复杂时,C++的优势就会体现出来。这也是许多——甚至可以说大多数——科学和工程中的仿真软件程序(比如业内领头的Abaqus、deal.II、FEniCS、OpenFOAM,以及CATIA等一些CAD软件)都用C++来实现的原因。得益于处理器和编译器的发展,C++也越来越多地应用到嵌入式系统中(不过可能不是全部的现代语言特性和库都可以使用)。此外,我们不确定有多少项目如果晚些启动就会转用C++,而不会使用C。比如,著名的科学库PETSc的作者Matt Knepley(也是本书作者的好友)就承认,如果有可能,他更愿意用C++重写这个库。
学习C++的理由
和其他语言不同,从硬件编程到高级抽象编程,C++几乎都能胜任。底层编程——如用户自定义的内存管理——可以让程序员明确掌握程序是如何被执行的,它也会帮助你更好地了解其他语言中程序的行为。使用C++可以编写极高性能的程序。这些程序仅仅比花大力气用机器语言精心编写的代码性能略差一些。况且,程序员应该优先让软件的实现清晰明了,“硬核”的性能调优只是其次。
而这正是C++高级特性的用武之地。C++直接支持各种编程范式:面向对象编程(见第6章)、泛型编程(见第3章)、元编程(见第5章)、并发编程(见4.6节)和过程式编程(见1.5节),等等。有好几种编程技术,比如RAII(见2.4.2.1节)和表达式模板(见5.3节)都是在C++中发明的。由于C++的语言表达能力非常强,所以通常可以在保持语言不变的条件下开发出新的技术。也许有一天你也会成为新技术的发明者。
阅读本书的原因
这本书中的所有内容都经过了实践检验。作者教授了三年(每年两个学期)C++ for Scientists课程。大部分学生来自数学系,还有一些来自物理和工程系。他们在课前通常并不了解C++,而在课程结束时,已经能够实现表达式模板(5.3节)等高级技术。你可以根据自己的需要阅读本书:直接跟随本书主章节学习要点,或者阅读附录A中的其他示例和背景知识以获得更多的信息。
“美女与野兽”
C++可以有多种编写方式。在本书中,我们会引导你平滑过渡到更加高级的风格上。这需要用到C++的高级特性。这些特性在最初可能会令人却步,但是习惯之后就会发现,高层 上的编程不仅适用面更广,在效率和可读性上也会更好。
我们使用恒定步长的梯度下降法这个简单的例子作为C++的入门用例。它的原理非常简单,我们以函数f(x)的梯度g(x)作为它最陡的方向进行下降,然后用固定大小的步长沿着这个方向抵达局部最小值。算法的伪代码也同样简单:
算法1:梯度下降法
输入:初始值x、步长s、终止条件ε、函数f、梯度g
输出:局部最小值x

对于这个简单的算法,我们提供了两个完全不同的实现。这里只需注意它的主要框架,不必考虑技术细节。

这两段代码乍看之下很相似,且让我们来仔细分析。第一个版本可以算是纯C的实现,用C语言编译器也可以编译它。它的好处是优化(optimize)的目标特别直观:一个双精度浮点的二维函数(在加粗部分中)。第二个版本是我们更喜欢的版本,因为它更加泛化:从被加粗的类型和函数参数上可以看到,它可以用具有任意值类型、任意维度的函数。出乎意料的是,拥有更多功能的后者在执行效率上并不落后于前者。相反,由F和G给出的函数可以被内联(见1.5.3节),以节省函数调用的开销。而左侧显式使用函数指针(也更难看)的版本则会令此类优化变得更加困难。
如果读者有耐心的话,可以在附录A(A.1节)中找到一个更长的新旧风格对比的例子。在实际工作中,现代风格的编程所带来的好处远比这里的示例更加明显。不过,在此我们不会举出更为复杂的例子,以免你耽于细节。
科学和工程计算中的编程语言
如果每种数值软件都可以用C++编写并保持高效,那当然是一件极好的事情。但前提是它们一定不能打破C++的类型系统。否则更应该使用Fortran、汇编语言或针对特定架构的扩展来进行编写。
——Bjarne Stroustrup
科学和工程计算软件可以使用不同的语言编写。而哪种语言最适合则取决于最终目标和可用资源:
?? 对于MATLAB、Mathmatica或者R这样的软件,当我们可以使用它们内建的算法时,它们会非常好用。但如果我们自己实现的算法需要细粒度的运算(例如标量),那么上述软件的性能会显著降低。不过如果问题规模较小或者用户有足够的耐心,这也可能不是问题。否则,我们就应该考虑其他的替代语言。
?? Python非常适合快速开发,并拥有类似SciPy或者NumPy这样的科学库。基于这些库(库本身通常由C或者C++开发)的应用程序的效率还是很高的。但是同样,需要细粒度运算的用户自定义算法的性能会降低。 使用Python是快速完成中小型任务的绝佳方式。但是当项目到一定规模后,更加严格的编译器就变得越来越重要(比如赋值会在参数不匹配时被拒绝)。
?? 当我们可以依赖现有的、经过良好优化的运算(比如密集矩阵计算)时,Fortran也是一个很不错的选择。它非常适合完成老教授的家庭作业(因为他们只会问一些在Fortran中很容易实现的问题)。根据作者的经验,当引入新的数据结构时,Fortran就会变得极为麻烦。事实上用Fortran编写大型模拟程序是一个相当大的挑战。如今愿意这样做的人越来越少。
?? C语言的性能很好,而且已有大量的软件使用C语言开发。它的语言核心内容较少,且易于学习。使用C语言开发所面临的主要挑战是:使用简陋而危险的语言特性,尤其是指针(见1.8.2节)和宏(见1.9.2.1节),开发大型、无错的软件。
?? 当应用程序最主要的部分是Web和图形界面并且计算较少时,Java、C#和PHP都是不错的选择。
当我们要开发具有良好性能的大型高质量软件时,C++在各项语言中可谓翘楚。这样的软件开发过程并不一定是缓慢而痛苦的。通过正确的抽象,我们可以非常快速地编写C++程序。一定会有更多的科学计算库被纳入未来的C++标准,我们对此表示乐观。
体例
本书中术语以中文楷体、英文斜体(italic)表示。C++源码使用等宽字体(monospace)。重要细节以粗体(boldface)标注。类、函数、变量和常量都是小写的,并可能含有下画线。矩阵例外,通常用单个大写字母命名。模板参数和概念(Concept)以大写字母开头,也可能会有其他的大写字母在名字中(CamelCase)。程序输出、命令行则用打字机字体(typewriter font)表示。
当需要使用C++03、C++11和C++14的特性时,程序会以相应的边框标注。一些轻度使用C++11特性,且易于被对应的C++03的机制替换的程序,就不再另行标注。

除了特别短的代码示例,本书中所有的程序示例都在至少一个编译器上进行了测试。完整程序的路径通常在包含这段代码的小节开头以箭头形式标出。
在Windows系统上还可以使用更方便的工具TortoiseGit(tortoisegit.org)。

目录
第1章 C++基础(C++ Basics) 1
1.1 第一个程序(Our First Program) 1
1.2 变量(Variables) 4
1.2.1 常量(Constants) 7
1.2.2 字面量(Literals) 7
1.2.3 非窄化的初始化(non-narrowing initialization) 9
1.2.4 作用域(Scopes) 11
1.3 操作符(Operators) 13
1.3.1 算术操作符(Arithmetic Operators) 14
1.3.2 布尔操作符(Boolean Operators) 17
1.3.3 位操作符(Bitwise Operators) 18
1.3.4 赋值(Assignment) 19
1.3.5 程序流(Program Flow) 19
1.3.6 内存处理(Memory Handling) 20
1.3.7 访问操作符(Access Operators) 21
1.3.8 类型处理(Type Handling) 21
1.3.9 错误处理(Error Handling) 21
1.3.10 重载(Overloading) 22
1.3.11 操作符优先级(Operator Precedence) 22
1.3.12 避免副作用(Avoid Side Effects!) 22
1.4 表达式和语句(Expressions and Statements) 25
1.4.1 表达式(Expressions) 25
1.4.2 语句(Statements) 26
1.4.3 分支(Branching) 27
1.4.4 循环(Loops) 29
1.4.5 goto 33
1.5 函数(Functions) 33
1.5.1 参数(Arguments) 34
1.5.2 返回结果(Returning Results) 36
1.5.3 内联(Inlining) 37
1.5.4 重载(Overloading) 38
1.5.5 main函数(main Function) 40
1.6 错误处理(Error Handling) 41
1.6.1 断言(Assertions) 41
1.6.2 异常(Exceptions) 43
1.6.3 静态断言(Static Assertions) 48
1.7 I/O 48
1.7.1 标准输出(Standard Output) 48
1.7.2 标准输入(Standard Input) 49
1.7.3 文件的输入和输出(Input/Output with Files) 49
1.7.4 泛化的流概念(Generic Stream Concept) 50
1.7.5 格式化(Formatting) 51
1.7.6 处理输入输出错误(Dealing with I/O Errors) 53
1.8 数组、指针和引用(Arrays, Pointers, and References) 56
1.8.1 数组(Arrays) 56
1.8.2 指针(Pointers) 58
1.8.3 智能指针(Smart Pointers) 62
1.8.4 引用(References) 65
1.8.5 指针和引用的比较(Comparison between Pointers and References) 66
1.8.6 不要引用过期数据(Do Not Refer to Outdated Data!) 67
1.8.7 数组的容器(Containers for Arrays) 67
1.9 软件项目结构化(Structuring Software Projects) 70
1.9.1 注释(Comments) 70
1.9.2 预编译指示字(Preprocessor Directives) 71
1.10 练习(Exercises) 75
1.10.1 年龄(Age) 75
1.10.2 数组和指针(Arrays and Pointers) 76
1.10.3 读取一个矩阵市场文件的头部(Read the Header of a Matrix
Market File) 76
第2章 类(Classes) 77
2.1 为普遍意义而不是技术细节编程(Program for Universal Meaning Not for
Technical Details) 77
2.2 成员(Members) 79
2.2.1 成员变量(Member Variables) 80
2.2.2 可访问性(Accessibility) 80
2.2.3 访问操作符(Access Operators) 83
2.2.4 类的静态声明符(The Static Declarator for Classes) 84
2.2.5 成员函数(Member Functions) 84
2.3 设置值:构造函数和赋值(Setting Values: Constructors and Assignments) 85
2.3.1 构造函数(Constructors) 86
2.3.2 赋值(Assignment) 96
2.3.3 初始化器列表(Initializer Lists) 97
2.3.4 一致性初始化(Uniform Initialization) 99
2.3.5 移动语义(Move Semantic) 101
2.4 析构函数(Destructors) 105
2.4.1 实现准则(Implementation Rules) 105
2.4.2 适当处理资源(Dealing with Resources Properly) 106
2.5 自动生成方法清单(Method Generation Résumé) 112
2.6 成员变量访问(Accessing Member Variables) 113
2.6.1 访问函数(Access Functions) 113
2.6.2 下标操作符(Subscript Operator) 115
2.6.3 常量成员函数(Constant Member Functions) 116
2.6.4 引用限定的变量(Reference-Qualified Members) 117
2.7 操作符重载的设计(Operator Overloading Design) 118
2.7.1 保持一致!(Be Consistent!) 119
2.7.2 注意优先级(Respect the Priority) 120
2.7.3 成员函数和自由函数(Member or Free Function) 120
2.8 练习(Exercises) 123
2.8.1 多项式(Polynomial) 123
2.8.2 移动赋值(Move Assignment) 123
2.8.3 初始化器列表(Initializer List) 123
2.8.4 资源管理(Resource Rescue) 124
第3章 泛型编程(Generic Programming) 125
3.1 函数模板(Function Templates) 125
3.1.1 实例化(Instantiation) 127
3.1.2 参数类型的推导(Parameter Type Deduction) 128
3.1.3 在模板中处理错误(Dealing with Errors in Templates) 132
3.1.4 混合类型(Mixing Types) 133
3.1.5 一致性初始化(Uniform Initialization) 134
3.1.6 自动返回值类型(Automatic return Type) 134
3.2 命名空间与函数查找(Namespaces and Function Lookup) 135
3.2.1 命名空间(Namespaces) 135
3.2.2 参数相关查找(Argument-Dependent Lookup) 138
3.2.3 命名空间限定还是ADL(Namespace Qualification or ADL) 142
3.3 类模板(Class Templates) 144
3.3.1 一个容器的范例(A Container Example) 144
3.3.2 为类和函数设计统一的接口(Designing Uniform Class and
Function Interfaces) 146
3.4 类型推导与定义(Type Deduction and Definition) 153
3.4.1 自动变量类型(Automatic Variable Type) 153
3.4.2 表达式的类型(Type of an Expression) 154
3.4.3 decltype(auto) 155
3.4.4 定义类型(Defining Types) 156
3.5 关于模板的一点点理论:概念(A Bit of Theory on Templates: Concepts) 158
3.6 模板特化(Template Specialization) 159
3.6.1 为单个类型特化类(Specializing a Class for One Type) 159
3.6.2 函数特化和重载(Specializing and Overloading Functions) 162
3.6.3 部分特化(Partial Specialization) 164
3.6.4 函数的部分特化(Partially Specializing Functions) 165
3.7 模板的非类型参数(Non-Type Parameters for Templates) 168
3.8 仿函数(Functors) 170
3.8.1 类似函数的参数(Function-like Parameters) 172
3.8.2 组合仿函数(Composing Functors) 173
3.8.3 递归(Recursion) 175
3.8.4 泛型归纳函数(Generic Reduction) 179
3.9 匿名函数(Lambda) 180
3.9.1 捕获(Capture) 181
3.9.2 按值捕获(Capture by Value) 181
3.9.3 按引用捕获(Capture by Reference) 182
3.9.4 广义捕获(Generalized Capture) 184
3.9.5 泛型匿名函数(Generic Lambdas) 185
3.10 变参模板(Variadic Templates) 186
3.11 练习(Exercises) 188
3.11.1 字符串表示(String Representation) 188
3.11.2 元组的字符串表示(String Representation of Tuples) 188
3.11.3 泛型栈(Generic Stack) 188
3.11.4 向量的迭代器(Iterator of a Vector) 189
3.11.5 奇数迭代器(Odd Iterator) 189
3.11.6 奇数范围(Odd Range) 189
3.11.7 bool变量的栈(Stack of bool) 190
3.11.8 自定义大小的栈(Stack with Custom Size) 190
3.11.9 非类型模板参数的推导(Deducing Non-type Template Arguments) 190
3.11.10 梯形公式(Trapezoid Rule) 190
3.11.11 仿函数(Functor) 191
3.11.12 匿名函数(Lambda) 191
3.11.13 实现make_unique(Implement make_unique) 191
第4章 库(Libraries) 192
4.1 标准模板库(Standard Template Library) 193
4.1.1 入门示例(Introductory Example) 193
4.1.2 迭代器(Iterators) 194
4.1.3 容器(Containers) 199
4.1.4 算法(Algorithms) 208
4.1.5 超越迭代器(Beyond Iterators) 215
4.2 数值(Numerics) 216
4.2.1 复数(Complex Numbers) 217
4.2.2 随机数发生器(Random Number Generators) 220
4.3 元编程(Meta-programming) 230
4.3.1 极限(Limits) 230
4.3.2 类型特征(Type Traits) 232
4.4 支持库(Utilities) 234
4.4.1 元组(Tuple) 235
4.4.2 函数(function) 238
4.4.3 引用包装器(Reference Wrapper) 240
4.5 就是现在(The Time Is Now) 242
4.6 并发(Concurrency) 244
4.7 标准之外的科学计算程序库(Scientific Libraries Beyond the Standard) 248
4.7.1 其他算术运算库(Other Arithmetics) 248
4.7.2 区间算术(Interval Arithmetic) 248
4.7.3 线性代数(Linear Algebra) 249
4.7.4 常微分方程(Ordinary Differential Equations) 249
4.7.5 偏微分方程(Partial Differential Equations) 249
4.7.6 图论算法(Graph Algorithms) 250
4.8 练习(Exercises) 250
4.8.1 按模排序(Sorting by Magnitude) 250
4.8.2 STL容器(STL Container) 250
4.8.3 复数(Complex Numbers) 250
第5章 元编程(Meta-Programming) 252
5.1 让编译器进行计算(Let the Compiler Compute) 252
5.1.1 编译期函数(Compile-Time Functions) 253
5.1.2 扩展的编译期函数(Extended Compile-Time Functions) 255
5.1.3 质数(Primeness) 257
5.1.4 此常数?彼常数?(How Constant Are Our Constants?) 259
5.2 提供和使用类型信息(Providing and Using Type Information) 260
5.2.1 类型特征(Type Traits) 261
5.2.2 条件异常处理(Conditional Exception Handling) 264
5.2.3 一个const整洁视图的用例(A const-Clean View Example) 265
5.2.4 标准类型特征(Standard Type Traits) 272
5.2.5 领域特定的类型属性(Domain-Specific Type Properties) 272
5.2.6 enable_if 274
5.2.7 新版变参模板(Variadic Templates Revised) 278
5.3 表达式模板(Expression Templates) 281
5.3.1 一个简单的操作符实现(Simple Operator Implementation) 281
5.3.2 一个表达式模板类(An Expression Template Class) 285
5.3.3 泛化的表达式模板(Generic Expression Templates) 288
5.4 元优化:编写你自己的编译器优化(Meta-Tuning: Write Your Own Compiler Optimization) 290
5.4.1 经典的固定大小的循环展开(Classical Fixed-Size Unrolling) 292
5.4.2 嵌套展开(Nested Unrolling) 295
5.4.3 动态循环展开――热身(Dynamic Unrolling―Warm-up) 301
5.4.4 展开向量表达式(Unrolling Vector Expressions) 303
5.4.5 调优表达式模板(Tuning an Expression Template) 305
5.4.6 调优缩减运算(Tuning Reduction Operations) 308
5.4.7 调优嵌套循环(Tuning Nested Loops) 316
5.4.8 调优一览(Tuning Résumé) 322
5.5 练习(Exercises) 323
5.5.1 类型特征(Type Traits) 323
5.5.2 Fibonacci数列(Fibonacci Sequence) 323
5.5.3 元编程版的最大公约数(Meta-Program for Greatest Common Divisor) 323
5.5.4 向量表达式模板(Vector Expression Template) 324
5.5.5 元列表(Meta-List) 325
第6章 面向对象编程(Object-Oriented Programming) 326
6.1 基本原则(Basic Principles) 327
6.1.1 基类和派生类(Base and Derived Classes) 327
6.1.2 继承构造(Inheriting Constructors) 331
6.1.3 虚函数和多态类(Virtual Functions and Polymorphic Classes) 332
6.1.4 基于继承的仿函数(Functors via Inheritance) 338
6.2 消除冗余(Removing Redundancy) 339
6.3 多重继承(Multiple Inheritance) 340
6.3.1 多个父类(Multiple Parents) 340
6.3.2 公共祖父(Common Grandparents) 342
6.4 通过子类型进行动态选择(Dynamic Selection by Sub-typing) 347
6.5 转换(Conversion) 350
6.5.1 在基类和派生类之间转换(Casting between Base and Derived Classes) 351
6.5.2 const转换(const-Cast) 356
6.5.3 重解释转型(Reinterpretation Cast) 356
6.5.4 函数风格的转型(Function-Style Conversion) 357
6.5.5 隐式转换(Implicit Conversions) 359
6.6 CRTP 359
6.6.1 一个简单的例子(A Simple Example) 360
6.6.2 一个可复用的访问操作符(A Reusable Access Operator) 361
6.7 练习(Exercises) 364
6.7.1 无冗余的菱形继承(Non-redundant Diamond Shape) 364
6.7.2 继承向量类(Inheritance Vector Class) 364
6.7.3 克隆函数(Clone Function) 364
第7章 科学计算项目(Scientific Projects) 365
7.1 常微分方程解算器的实现(Implementation of ODE Solvers) 365
7.1.1 常微分方程(Ordinary Differential Equations) 366
7.1.2 龙格-库塔法(Runge-Kutta Algorithms) 368
7.1.3 泛型实现(Generic Implementation) 369
7.1.4 展望(Outlook) 376
7.2 创建工程(Creating Projects) 377
7.2.1 构建过程(Build Process) 378
7.2.2 构建工具(Build Tools) 382
7.2.3 分离编译(Separate Compilation) 386
7.3 最终的话(Some Final Words) 391
附录A 杂谈(Clumsy Stuff) 393
A.1 更多好的或者不好的软件(More Good and Bad Scientific Software) 393
A.2 细节中的基础(Basics in Detail) 400
A.2.1 关于字面量修饰的其他事项(More about Qualifying Literals) 400
A.2.2 静态变量(static Variables) 401
A.2.3 关于if的其他事项(More about if) 402
A.2.4 达夫设备(Duff’s Device) 404
A.2.5 关于main的其他事项(More about main) 404
A.2.6 异常还是断言?(Assertion or Exception?) 405
A.2.7 二进制I/O(Binary I/O) 406
A.2.8 C风格的I/O(C-Style I/O) 407
A.2.9 垃圾收集(Garbage Collection) 408
A.2.10 宏的麻烦(Trouble with Macros) 409
A.3 现实世界的用例:矩阵求逆(Real-World Example: Matrix Inversion) 411
A.4 类的一些细节(Class Details) 421
A.4.1 指向成员的指针(Pointer to Member) 421
A.4.2 更多的初始化例子(More Initialization Examples) 422
A.4.3 多维数组的存取(Accessing Multi-dimensional Arrays) 423
A.5 方法的生成(Method Generation) 426
A.5.1 控制生成的代码(Controlling the Generation) 428
A.5.2 代码生成的规则(Generation Rules) 429
A.5.3 陷阱和设计指南(Pitfalls and Design Guides) 434
A.6 模板相关的细节(Template Details) 438
A.6.1 统一初始化(Uniform Initialization) 438
A.6.2 哪个函数被调用了?(Which Function Is Called?) 439
A.6.3 针对特定硬件的特化(Specializing for Specific Hardware) 442
A.6.4 变参二进制I/O(Variadic Binary I/O) 443
A.7 使用C++03中的std::vector(Using std::vector in C++03) 444
A.8 复古风格的动态选择(Dynamic Selection in Old Style) 445
A.9 元编程的一些细节(Meta-Programming Details) 446
A.9.1 历史上的第一个元程序(First Meta-Program in History) 446
A.9.2 元函数(Meta-Functions) 448
A.9.3 向下兼容的静态断言(Backward-Compatible Static Assertion) 450
A.9.4 匿名类型参数(Anonymous Type Parameters) 450
A.9.5 “动态循环展开”的性能基准测试源码(Benchmark Sources of
Dynamic Unrolling) 454
A.9.6 矩阵乘法的性能基准测试(Benchmark for Matrix Product) 455
附录B 编程工具(Programming Tools) 456
B.1 gcc 456
B.2 调试(Debugging) 457
B.2.1 基于文本的调试器(Text-Based Debugger) 458
B.2.2 使用图形界面DDD进行调试(Debugging with Graphical Interface: DDD) 460
B.3 内存分析(Memory Analysis) 462
B.4 gnuplot 463
B.5 UNIX、Linux和macOS系统(UNIX, Linux, and macOS) 464
附录C 语言定义(Language Definitions) 467
C.1 值类别(Value Categories) 467
C.2 操作符概览(Operator Overview) 468
C.3 类型转换规则(Conversion Rules) 470
C.3.1 类型提升(Promotion) 471
C.3.2 其他类型提升(Other Conversions) 471
C.3.3 常用的数值转换(Usual Arithmetic Conversions) 472
C.3.4 窄化(Narrowing)
短评

我们的生活方式是什么时候回来呀,

2020-07-30 18:42:26

这本书的编写结构是我喜欢的!

2020-07-28 13:01:09

还不错,学习一下新的标准

2020-07-28 12:45:35

学习编程语言

2020-07-26 13:33:23

又很多干货,值得一读

2020-07-24 07:35:06

新书,买来学习一下!

2020-07-23 11:53:29

学习c++,涨知识,棒棒棒,虽然不是最新的标准,但是也值得学习

2020-07-21 07:38:51