C++是一门经典的编程语言,堪称编程语言中的“全能选手”,它不仅功能强大、灵活,而且适用场景非 常广泛。但是要想真正掌握 C++, 其技术门槛往往较高, 这也使“新手”学起来困难, 甚至连“老手”也觉 得用好它并不容易。
大多数人都能写出机器能看懂的代码,但只有优秀的程序员才能写出任何人都能看懂的 代码。
有两种写程序的方式:一种是把代码写得非常复杂, 以至于“看不出明显的错误”;另一 种是把代码写得非常简单, 以至于“明显看不出错误”。
把正确的代码改快速”要比“把快速的代码改正确”容易太多。
说起 C++, 很多人还会有另一个反应— “出了名的难学难用”。的确如此,因为 C++实在是太复杂了,有太多的特性和细节。
2021年最受欢迎的C++书,从以下几本C++书籍踏上学习之旅吧!
1、C++ Primer Plus 第6版 中文版
适读人群:初学者
如果已经对C有所了解,便可以学习C++了,但这并不仅仅是学习更多的关键字和结构,从C过渡到C++的学习量就像从头学习C语言一样大。另外,如果先掌握了C语言,则在过渡到C++时,必须摒弃一些编程习惯。如果不了解C语言,则学习C++时需要掌握C语言的知识、OOP知识以及泛型编程知识,但无需摒弃任何编程习惯。如果您认为学习C++可能需要扩展思维,这就对了。本书将以清晰的、帮助的方式,引导读者一步一个脚印地学习,因此扩展思维的过程是温和的,不至于让您的大脑接受不了。
本书通过传授C语言基础知识和C++新增的内容,带您步入C++的世界,因此不要求读者具备C语言知识。首先学习C++与C语言共有的一些特性。即使已经了解C语言,也会发现阅读本书的这一部分是一次很好的复习。另外,本章还介绍了一些对后面的学习十分重要的概念,指出了C++和C之间的区别。在牢固地掌握了C语言的基础知识后,就可以在此基础上学习C++方面的知识了。那时将学习对象和类以及C++是如何实现它们的,另外还将学习模板。
本书在介绍C++特性的同时,还讨论了基本C语言,使两者成为有机的整体。书中介绍了C++的基本概念,并通过短小精悍的程序来阐明,这些程序都很容易复制和试验。书中还介绍了输入和输出,如何让程序执行重复性任务,如何让程序做出选择,处理数据的多种方式,以及如何使用函数等内容。另外,本书还讲述了C++在C语言的基础上新增的很多特性,包括:
- 类和对象;
- 继承;
- 多态、虚函数和RTTI(运行阶段类型识别);
- 函数重载;
- 引用变量;
- 泛型(独立于类型的)编程,这种技术是由模板和标准模板库(STL)提供的;
处理错误条件的异常机制;
- 管理函数、类和变量名的名称空间。
全书分18章,分别介绍了C++程序的运行方式、基本数据类型、复合数据类型、循环和关系表达式、分支语句和逻辑运算符、函数重载和函数模板、内存模型和名称空间、类的设计和使用、多态、虚函数、动态内存分配、继承、代码重用、友元、异常处理技术、string类和标准模板库、输入/输出、C++11新增功能等内容。
本书针对C++初学者,从C语言基础知识开始介绍,然后在此基础上详细阐述C++新增的特性,因此不要求读者有C语言方面的背景知识。本书可作为高等院校教授C++课程的教材,也可供初学者自学C++时使用。
2、C++实战笔记
适读人群:比较适合学过 C++基础知识,仍缺乏高效的 C++实战技巧的读者阅读。
本书根据作者 20 多年编写 C++代码的实践经验,精选出了现代 C++中好用且实用的若干特性,通过代 码演示实战技巧, 帮助读者轻松地看懂、学会 C++编程。本书从开发环境、开发综述、核心语言特性、标准 库、进阶技能、设计模式、应用实例等方面深入浅出地介绍了 C++实战技巧。除此之外, 本书还囊括了作者 多年的开发心得,例如经典图书推荐、工作经验分享、时间管理方法等特色内容。
本书并不是一本入门教程,比较适合学过C++基础知识,仍缺乏高效的C++实战技巧的读者阅读。通过阅读本书,读者可以深入洞悉C++核心知识,进一步夯实实战技能,开拓编程思路。
本书的目标就是一切从实际出发,只讲“实实在在、脚踏实地”的 C++知识,注 重语言和库的“开发”,而不会讲那些高深的理论和玄乎的技巧,更不会去讲所谓的“屠龙之术”, 尽量用实例来演示“现代 C++”的自然思维方式。①
另外,因为 C++的资料已经有很多了, 我也不想变成标准的复读机,去机械地重复那些接口 定义。本书通常只会简单提一下语言要点,不会详细解释调用方式, 重点聚焦在使用时的注意事 项和经验教训(用法细节完全可以去查在线资料)。
作者建议:尽量从 C++的最新标准开始学,例如现在的 C++17/C++20。这两个版本的 C++ 虽然比以前版本的复杂了很多,但也添加了很多方便、易用的新特性,更接近“现代编程语言”。 只要小心取舍,就可以少遇到那些传统编程方式的“坑”。
3、C++并发编程实战(第2版)
适读人群:适合需要深入了解C++多线程开发的读者,以及使用C++进行各类软件开发的开发人员、测试人员,
本书是一份深度指南,内容是 C++新标准中涉及的并发与多线程功能,从std::thread、std::mutex和std::async的基本使用方法开始,一直到复杂的内存模型和原子操作。
如果你要用C++编写多线程代码,就应该阅读本书;如果你想使用C++标准程序库中的多线程工具,那么本书可作为基础指南;如果你要用到其他线程库,本书后面的章节也给出了指导原则和技巧,仍会让你获益。
我假设读者已具备了良好的C++实操知识,却不太熟悉C++的新特性。为此,附录A将补充相关内容。
本书从C++标准程序库的各种工具讲起,介绍线程管控、在线程间共享数据、并发操作的同步、C++内存模型和原子操作等内容。同时,本书还介绍基于锁的并发数据结构、无锁数据结构、并发代码,以及高级线程管理、并行算法函数、多线程应用的测试和除错。本书还通过附录及线上资源提供丰富的补充资料,以帮助读者更完整、细致地掌握C++并发编程的知识脉络。
4、C++语言的设计和演化
本书是C++的设计者Bjarne Stroustrup关于C++语言的最主要著作之一(另一本是《C++程序设计语言》)。在这本书中,作者全面论述了C++ 的历史和发展,C++中各种重要机制的本质、意义和设计背景,这些机制的基本用途和使用方法,讨论了C++所适合的应用领域和未来发展前景。本书在帮助人们深入理解C++ 语言方面的地位无可替代,值得每个关心、学习和使用C++ 语言的专业工作者、科研人员、教师和学生阅读。在这本书中,作者还从实践的角度出发,讨论了许多与程序设计语言、系统程序设计、面向对象的技术和方法、软件系统的设计和实现技术等有关的问题,值得每一个关心这些领域及相关问题的计算机工作者和学生们阅读参考。
5、现代C++语言核心特性解析
《现代C++语言核心特性解析》(谢丙堃)【摘要 书评 试读】- 京东图书item.jd.com/12942311.html正在上传…重新上传取消
适读人群:本书的读者需要具有一定的C++基础,并且想要学习C++新特性或者因为工作项目需要学习C++新特性。
本书并不是直接告诉读者C++11~C++20的新特性该怎么使用,而是希望读者通过本书能够了解新特性诞生的前因后果,用实际例子探讨过去C++中的缺陷以及新特性如何修复和完善优化,并且尽可能地描述新特性在编译器中的实现原理。它没有告诉读者“你应该这样使用这个新特性”,而是在说“嘿,我有一个不错的新特性,可以解决你手中的问题,它的原理是……而且关于这个特性我还有一个小故事,想听听么?”另外,为了保证新特性被编译器切实有效地实现,本书中几乎所有的代码都采用GCC、CLang和MSVC编译过。在编译器表现与C++标准描述不一致的时候会提醒读者注意其中的区别。
关于学习C++的几点疑问(摘自C++的设计者Bjarne Stroustrup的《++语言的设计和演化》一书)
C++ 使用的成长及其性质,已经受到学习C++ 的方式的强有力影响。由此可知,如果对应该如何教和学C++ 缺乏认识的话,要想理解它就可能比较困难。如果缺乏这方面的认识,可能就无法理解C++的快速成长的某些方面。
关于应该如何有效地将C++ 教给相对而言的新手,如何使他们能有效地使用学到的东西,这些问题从很早就影响着C++ 的设计。我做了许多教学工作——至少是做了许多教授某些研究者(并不是专业的教育工作者)的工作。我一直设法将自己的想法传播出去,在观察自己和别人所教的人们写出的实际程序方面,有许多成功与失败,这些都对C++ 的设计产生了重要影响。
我没有多少时间去学习新技术和新概念,在这种情况下我怎样才能有效地开始使用C++?
我对C或C++ 都不了解,是不是应该先学习C?不,首先学习C++。C++ 的C子集对于C/C++ 的新手是比较容易学的,又比C本身容易使用。原因是C++(通过强类型检查)提供了比C更好的保证。进一步说,C++ 还提供许多小特征,例如运算符new
,与C语言对应的东西相比,它们的写法更方便,也更不容易出错。这样,如果你计划学习C和C++(而不只是C++),你不应该经由C那条迂回的路径。为能很好地使用C,你需要知道许多窍门和技术,这些东西在C++ 里的任何地方都不像它们在C里那么重要、那么常用。好的C教科书倾向于(也很合理)强调那些你将来在用C做完整的大项目时所需要的各种技术。好的C++ 教科书则不太一样,强调能引导你去做数据抽象、面向对象的程序设计的技术和特征。理解了C++ 的各种结构,而后学习它们在(更低级的)C里替代物将会很简单(如果需要的话)。
要说我的喜好:要学习C,就用 [Kernighan,1988];要学习C++,就用[2nd]。两本书的优点是都组合了两方面内容:一方面是关于语言特征和技术的指导性的描述,另一方面是一部完整的参考手册。两者描述的都是各自的语言而不是特定的实现,也不企图去描述与特定实现一起发布的特殊程序库。
现在有许多很好的教科书和许多各种各样风格的材料,上面只是我对理解有关概念和风格的喜好。请仔细选择至少两个信息来源,以弥补可能的片面性甚至缺陷,这样做永远是一种明智之举。
我想做OOP,那么,是不是应该在学习C++之前先学Smalltalk?不。如果你计划用C++,那就学C++。各种语言,像C++、Smalltalk、Simula、CLOS和Eiffel等,各有自己对于抽象和继承等关键概念的观点,各语言以略微不同的方式支持着这些概念,也支持不同的设计概念。学习Smalltalk当然能教给你许多有价值的东西,但它不能教给你如何在C++ 里写程序。实际上,除非你有充分时间学习和消化Smalltalk以及C++ 的概念和技术,否则用Smalltalk作为学习工具将导致拙劣的C++ 设计。
当然,如果同时学了C++ 和Smalltalk,能使你取得更广泛领域中的经验和实例,那当然是最理想的。但是那些不可能花足够时间去消化所有新概念的人们常常最后是‘在C++ 里写Smalltalk’,也就是说,去用那些并不能很好适应C++ 的Smalltalk设计概念。这样写出的程序可以像在C++ 里写C或Fortran一样,远不是最好的东西。
常见的关于学习Smalltalk的理由是它‘很纯’,因此会强迫人们去按‘面向对象的’方式思考和编程。我不想深入讨论‘纯’的问题,除提一下之外。我认为一个通用程序设计语言应该而且也能够支持一种以上的程序设计风格(范型)。
这里的问题是,适合Smalltalk并得到它很好支持的风格并不一定适合C++。特别是模仿性地追随Smalltalk风格,将会在C++ 里产生低效、丑陋,而且难以维护的C++ 程序。个中理由很简单,好的C++ 程序所需要的设计应该能很好地借助C++ 静态类型系统的优势,而不是与之斗争。Smalltalk(只)支持动态类型系统,把这种观点翻译到C++ 将导致广泛的不安全性和难看的强制转换。
我把C++ 程序里的大部分强制转换看作是设计拙劣的标志。有些强制转换是很基本的,但大部分都不是。按我的经验,传统C程序员使用C++,通过Smalltalk理解OOP的C++ 程序员是使用强制转换最多的人,而所用的那些种类的转换,完全可以通过更仔细的设计而得以避免。
进一步说,Smalltalk鼓励人们把继承看作是唯一的,或者至少是最基本的程序组织方式,并鼓励人们把类组织到只有一个根的层次结构中。在C++ 里,类就是类型,并不是组织程序的唯一方式。特别的是,模板是表示容器类的最基本方法。
我也极端怀疑一种论断,说是需要强迫人们去采用面向对象的风格写程序。如果人们不想去学,你就不可能在合理的时间内教会他们。按我的经验,确实愿意学习的人从来也不短缺,最好还是把时间和精力用到他们身上。除非你能把握住如何表现隐藏在数据抽象和面向对象的程序设计后面的原理,否则你能做的不过是错误地使用支持这些概念的语言特征,而且是以一种不适当的‘巴罗克’形式[2]——无论在C++、Smalltalk或者其他语言里。
参看《C++ 程序设计语言》(第2版) [2nd],特别是第12章,那里有关于C++ 语言特征和设计之间关系的更多讨论。
我在一开始应该把C++ 作为一种OOPL,还是作为一个更好的C语言?看情况。为什么你想开始用C++?对这个问题的回答应该能确定你走近C++ 的方式,在这里,没有某种放之四海而皆准的道理。按照我的经验,最安全的方式是自下而上地学习C++,也就是说,首先学习C++ 所提供的传统的过程性程序设计特征,也就是那个更好的C子集;而后学着去使用和遵循那些数据抽象特征;再往后学习使用类分层去组织相互有关的类的集合。
按照我的观点,过快地通过早期阶段是很危险的,这样会使忽视某些重要概念的可能性变得非常之大。
例如,一个有经验的C程序员可能会认为C[3]的更好的C子集是‘很熟悉的’,因此跳过了教科书中描述这方面的前100页或多少页。但在这样做时,这个C程序员可能就没看到有关函数的重载能力,有关初始化和赋值之间差异的解释,用运算符new
做存储分配,关于引用的解释,或许还有其他一些小特征。在后面阶段它们会不断地跳出来缠住你,而在这时,一些真正的新概念正在复杂的问题中发挥着作用。如果在更好的C中所用的概念都是已知的,读过这100页可能也就只要几个小时的时间,其中的一些细节又是有趣的,很有用的。如果没有读,后面花的时间可能更多。
有些人表达了一种担心,害怕这种‘逐步方式’会引导人们永远去写C语言风格的东西。这当然是一种可能的后果,但是从百分比看,与在教学中采用‘更纯的’语言或者强迫的方式相比,很难说这样做就一定更不值得信任。关键是应该认识到,要把C++ 很好地用作数据抽象和/或面向对象的语言,应该理解几个新概念,而它们与C或者Pascal一类语言并不是针锋相对的。
C++ 并不只是用新语法表述一些老概念——至少对于大部分程序员而言不是这样。这也就隐含着教育的需要,而不仅仅是训练。新概念需要通过实践去学习和掌握。老的反复试验过的工作习惯需要重新评价。不再是按照‘老传统的方式’向前冲,而是必须考虑新方式——通常,与按照老方式相比,以新方式做事情,特别是第一次这样做时,一定更困难,也更费时间。
许多经验说明,对大部分程序员而言,花时间和精力去学习关键性的数据抽象和面向对象技术,是非常有价值。并不是必须经过很长的时间才能产生效益,一般在3到12个月就可以。不花这些精力,而只是使用C++,也会有效益,但最大的效益还是要在为学习新概念而花费精力之后——我的疑问是,如果什么人不想花这个精力,那么为什么还要转到C++ 来呢。
在第一次接触C++,或是在许多时间之后又第一次接触它,用一点时间去读一本好的教科书,或者几篇经过很好选择的文章(在The C++ Report和The C++ Journal里有许多这样的文章)。你也可能想看看某些主要的库的定义和源代码,分析其中使用的概念和技术。对那些已经用了一段C++ 的人来说,这也是个好主意,在重温这些概念和技术的过程中可以做许多事情。自C++ 第一次出现以来,在C++ 语言以及与之相关的编程和设计技术方面已经发生过许多事情。将《C++ 程序设计语言》的第1版和第2版做一个简单对比,就足以使人相信这个说法。
学习C++ 需要花多少时间?同样要看情况。依赖于你的经验,也依赖于你所说的‘学习C++’的意思。对大部分程序员而言,学习语法和用更好的C的风格写C++,再加上定义和使用几个简单的类,只要一两周时间。这是最容易的部分。最主要的困难在于掌握新的定义和编程技术,这也是最有意思、最有收获的部分。曾经和我讨论过的大部分有经验的程序员说,他们用了半年到一年半时间,才真正觉得对C++ 适应了,掌握了它所支持的数据抽象和面向对象技术。这里假定他们是在工作中学习并维持着生产——通常在此期间也用着C++的某种‘不那么大胆’的风格做程序设计。如果你能拿出全部时间学C++,就可能更快地适应它。但是,在没有将新的思想和设计应用到真实的项目中之前,这个适应也很可能是骗人的。面向对象的编程和面向对象的设计,基本上是实践性的训练而不是理论训练。只是对一些玩具式的小例子使用或者不使用它,这些思想就很可能演化为一种危险的盲从倾向。
请注意,学习C++,最根本的是学习编程和设计技术,而不是语言细节。在做完了一本教科书的学习工作之后,我会建议一本有关设计的书,例如 [Booch,1991] ,该书里有一些稍长的例子,用的是5种语言(Ada、CLOS、CLU、C++、Smalltalk和Object Pascal),这样就可能在某种程度上避免语言的偏狭性,而偏狭性已经弄糟了许多有关设计的讨论。在这本书里,我最喜欢的部分就是描述设计概念和例子的那几章。
关注设计方式,与非常仔细地关注C++ 的定义细节(例如ARM,其中包含许多有用的信息,但是没有关于如何用C++ 编程的信息)是截然不同的。把注意力集中到细节上,很容易把人搞得头昏脑涨,以至于根本就用不好语言。你大概不会试着从字典和语法去学习一种外国语吧?
在学习C++ 时,最根本的,应该是牢记关键性的设计概念,使自己不在语言的技术细节中迷失了方向。如果能做到这一点,学习和使用C++ 就会是非常有趣的和收效显著的。与C比较,用一点点C++ 就可能带来许多收获。在理解数据抽象和面向对象技术方面付出进一步努力,你将能得到更多的收获。”
这个观点也不是全面的,受到当前工具和库的状况的影响。如果有了保护性更强的环境(例如包括了广泛的自动的运行时检查)以及一个小的定义良好的基础库,你就可以更早地转到大胆使用C++ 的方面去。这些将能更好地支持从关注C++ 的语言特征到关注C++ 所支持的设计和编程技术的大转移。
分散一些兴趣放到语法上,把一些时间用到语言的技术细节上,也是非常重要的。有些老牌程序员喜欢翻弄这些细节。这种兴趣与不大情愿去学习新的程序设计技术,经常是很难分辨清楚的。
类似地,在每个课程和每个项目里总有这样的人,他们根本不相信C++ 的特征是可以负担得起的,因此在后来的工作中坚持使用自己更熟悉和信任的C子集。只有不多的有关个别C++ 特征和用C++ 写出的系统的执行效率方面的数据(例如,[Russo,1988]、[Russo,1990]、[Keffer,1992]),不大可能动摇这些人长期而牢固的,有关比C更方便的机制是不可能负担的观点。看到这种宣传的量,与语言或工具领域中未得到满足的允诺的量的比较,人们应该对这种说法持怀疑态度,并要求拿出更明显的证据。
在每个课程和项目里也总有另一种人,他们确信效率无关紧要,倾向于用更一般的方式去设计系统,结果是,即使在最先进的硬件上也产生了可观察到的延迟。不幸的是,这种延迟在人们学习C++ 的过程中写玩具程序时很难观察到,因此具有这种性质的问题常常被遗留下来,直到遇到真正的项目。我一直在寻找一个简单但又实际的问题,如果采用一种过分一般的方式去解决,它就能打倒一个很好的工作站。这样的问题将使我能证明带有倾向性的设计的价值,以抵制那些极端的乐观主义者;而通过仔细思考又能使性能大大改善,可以对付过于谨慎和保守的人们。