如今科学工程项目越来越大、越来越复杂,许多项目都采用C++ 编程语言来完成。本书深入介绍了基于C++ 编程语言高级功能的复杂方法,旨在帮助您快速入门,实现如表达式模板之类的高级技术。您还将学习如何使用C++ 编程语言的强大类库:标准模板库(STL)以及用于算法、线性代数、微分方程、图形的科学类库。书中演示了如何使用面向对象、泛型编程、元编程和过程技术来编写清晰明了、富有表达力的软件。当您学完本书,将掌握如何使用C++ 编程语言来编写高质量、高性能的软件。
? 经典原味,基于C++14,编码、工程与科研必修。
? 深入介绍,快速入门C++,编写高质量、高性能软件。
? 本书作者为C++标准委员会成员,拥有丰富的C++教学经验。
前言
世界由C++ (以及它的C子集)构建。
—— Herb Sutter
Google、Amazon和Facebook的基础架构很多都由C++构建。此外,相当一部分底层技术也是由C++实现的。在电信领域,几乎所有固定电话和手机的连接都由C++软件驱动。最重要的是,德国所有主要传输节点都是用C ++处理的,这意味着笔者的家庭也依赖于C ++软件。
即便是由其他语言撰写的软件也会依赖于C++,因为最流行的编译器如Visual Studio、Clang、Gnu编译器包和Intel编译器都是用C++实现的。Windows平台上的程序也多由C++实现,如Microsoft Office套件。可以说C++是无所不在的。甚至您的手机和汽车也会包含由C ++开发的组件。C++的发明者Bjarne Stroustrup制作了一个网页,列出了由C++开发的应用清单,上文的例子也多源自于这个网页。
在科学和工程中,许多高质量的软件包都是用C++实现的。当项目超过一定大小且数据结构非常复杂的情况下更能凸显C++的强大能力。这也是为什么大量科学和工程模拟软件都 使用C++的原因。随便举几个例子,比如该领域的领头羊Abaqus、deal.II、FEniCS以及OpenFOAM。知名CAD软件CATIA也由C++开发。得益于更强大的处理器和改进的编译器, C++在嵌入式系统上的应用也越来越多。当然,并不是所有的现代语言特性和库都可以用在这些平台上。
最后,如果一个项目可以重新开发,我们不知道有多少项目会使用C++而不是C实现。例如,作者的好友Matt Knepley是非常成功的科学计算程序库PETSc的作者之一,如果可以重写这个库的话,他会选择C++来实现它。
学习C++的理由
和其他语言不同,从充分贴近硬件的开发,到高级抽象的开发,C++几乎都能胜任。底层开发——比如用户定制的内存管理(User defined memory management)——可以让程序员了解程序执行过程中的细节,也能帮助您理解由其他语言开发的程序的行为。利用C++可以编写执行效率非常高的程序,仅仅可能比使用机器语言编写的程序慢上一点点,但是后者要付出更多的努力。然而,在死磕性能调优之前(Hardcore Performance Tuning),您应该首先关注如何开发逻辑清晰、表达准确的程序。
而这正是C++高层特性的用武之地。C++直接支持多种编程范式(Programming Paradigms):面向对象编程(Object Oriented Programming)(第6章)、泛型编程(Generic Programming)(第3章)、元编程(Metaprogramming)(第5章)、并发编程(Concurrent Programming)(见4.6节)和过程化编程(Procedural Programming)(见1.5节),等等。C++还发明了好几种编程技术,例如RAII(见2.4.2.1节)和表达式模板(Expression templates)(见5.3节)。C++的表达能力如此之强,故而经常可以在不改变语言的情况下发明新的技术。也许有一天您也会发明一种新的技术呢。
阅读本书的理由
本书素材已经经过了多人的检验。作者执教课程C++ for Scientist已有三年,每年两个学期。这门课的学生多来自于数学系,也有一些来自于物理和工程专业。在课程学习之前,他们通常没有C++基础,但在学完这门课程后就可以实现如表达式模板(见5.3节)之类的高级技术。您可以按照自己的节奏阅读本书:直接跟着本书路线完成学习,或者通过阅读附录A,了解更多示例和背景知识。
美女与野兽
编写C++程序有多种方式,本书将循序渐进地指导读者使用更加高级的风格。这需要使用到C++的高级特性。这些特性看起来挺吓人,但是习惯之后,它们不仅应用更加广泛,也更为高效且易读。
我们用下面这个例子作为您对C++的第一印象:恒定步长的梯度下降法。原理非常简单,用其梯度函数例如g(x)来计算f(x)的最陡下降,并且用固定大小的步长追随这个梯度方向到相邻的局部最小值。 算法的伪代码也非常简单:
算法1:梯度下降算法
输入:初始值x,步长s,终止条件epsilon,函数f,梯度函数g
输出:局部最小值x
这个简单算法我们提供了两种实现。我们看一下下面代码并思考一下,不考虑它们的技术细节。
它们看起来非常相似,但我们会告诉您哪一个是我们喜欢的。第一个版本差不多是纯C语言,您可以用C编译器编译。这个版本的好处就是看起来很直观,使用double类型的2D函数。但是我们更喜欢第二个版本,因为它用途更广,具有任意值类型的任意维度函数。令人惊奇的是这个多功能的版本并没有降低效率。相反,函数F和G可以内联(见1.5.3节)节省了函数调用开销,而在左边版本中显式的(丑陋的)函数指针使得这种优化变得更困难。
如果您是一个有耐心的读者,就可以在附录A中(A.1)找个一个比较新旧样式的更详细的例子。附录中的案例更能体现使用现代风格编程的好处。当然,我们不希望您为这些新旧样式的小冲突折腾太久。
科学和工程领域的计算机语言
“如果所有的数值类软件都在可以用C++编写而不损失效率,那自然很好。但在我们找到一种既能高效计算,又不违反C++类型系统的方法之前,还是用Fortran、汇编,或者针对体系结构优化过的方法更好。”
——Bjarne Stroustrup
科学计算和工程软件可以使用不同的编程语言编写,而哪种语言最合适则主要取决于我们的目标和可用的资源。
? 当我们仅使用现有算法时,那么最好选择数学工具软件如MATLAB、Mathematica、R等。但如果希望在它们的基础上通过一些细粒度的运算(如标量计算)实现自己的算法,那么我们会发现它的性能将显著下降。当然如果问题本身很小,或者用户非常有“耐心”,这自然不是问题。否则,就需要寻找其他语言来实现我们的问题。
? Python非常适合快速开发。它也包含了大量科学计算的库,比如scipy和numpy。使用这些库(这些库本身通常由C或者C++实现),我们也能开发出很高效的应用程序。和数学工具软件一样,细粒度实现的用户定义算法也会牺牲性能。如果要快速实现中小型任务,Python非常适合。但如果项目足够大,编译器的重要性就会逐渐体现出来(例如当参数不匹配时拒绝赋值)。
? Fortran也会适用于工程和科学计算,因为Fortran上拥有大量经过充分优化的操作,如密集矩阵运算。它非常适合完成那些老派教授的作业(这些作业本身很适合Fortran)。而依据作者的经验,在Fortran中引入新的数据结构非常麻烦,因此在Fortran中编写一个大规模的模拟程序是个相当大的挑战——在今天,这样的选题只有少数人能勉为其难地接受。
? C语言有着很好的性能,用C编写的软件数量非常多。C的语言核心小,易于学习。使用C语言开发的挑战在于,需要使用简陋而危险的语言特性例如指针(见1.8.2节)和宏(见1.9.2.1节)去实现大型的、无Bug的软件。
? 当应用程序的主要组件Web或图形界面组件没有特别密集的运算时,Java、C#、PHP这一类的语言是非常好的选择。
? 开发大型、高质量、高性能的应用程序是C++尤为擅长的。并且开发过程也不会十分漫长而痛苦。通过正确的抽象,可以飞快地编写C++程序。在未来会有更多的科学计算库出现在C++标准中。
显然,我们所了解的语言越多,选择的余地也就越大;对语言了解的越深入,我们做出的选择也越明智。此外,大型项目也常包含多个用不同语言开发的组件,多数情况下起码性能关键的内核部分都是由C或者C++实现的。总而言之,学习C++一定是一段有趣的过程,深入理解它,一定能帮助您成为一名出色的程序员。
体例
新术语使用斜体(italic)。C++源代码使用等宽字符(monospace)。一些重要的细节被标记为粗体(boldface)。
类、函数、变量与常量一律使用小写字母,也可能会用到下划线。矩阵使用特殊的标记,我们一般使用单个大写字母来代表矩阵。模板参数和Concepts以大写开头,大写分割(CamelCase)。程序输出和命令行,使用打字机字体(typewriter font)。
如果程序需要C++3、C++11或者C++14的特性,会用相应的边框来表示。一部分程序仅使用了少量C++11的特性,且很容易替换成C++3的实现,对于它们我们不再另行标注。
? directory/source_code.cpp。
除了一些特别短小的演示代码,所有编程实例都至少在一个编译器上测试过。在段落或小节的开头,我们会用箭头指示出所讨论的代码的路径。
所有程序都作为公有代码仓库置放在Github上:https://github.com/ petergottschling/discovering_modern_cpp。您可以使用以下命令来克隆代码仓库:
git clone https://github.com/petergottschling/discovering_modern_cpp.git。
在Windows上还可以使用更方便的工具TortoiseGit(tortoisegit.org)