书籍作者:[德] 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)。
我们的生活方式是什么时候回来呀,
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