丹麦计算机科学家Bjarne Stroustrup于1982年发明了C++;C++继承于C,同时引入了类。1985年,发布了第一版的“C++程序设计语言”。第一个标准化版本的C++在1998年发布,称为C++98。在2003年,C++03发布并包含了一些小的更新。在那之后,C++沉默了一段时间,但吸引力开始慢慢增强,导致该语言在2011年进行了重大更新,称为C++11。从那以后,C++标准委员会以3年为周期发布更新的版本,出现了C++14、C++17、C++20及现在的C++23。总之,2023年发布了C++23之后,C++已经将近40岁了,并且仍然很强大。在2023年的大多数编程语言排名中,C++都排在前4位。它被广泛用于各种硬件,从带有嵌入式微处理器的小型设备一直到超级计算机。除了广泛的硬件支持,C++还可以用来完成几乎任何编程工作,包括移动平台上的游戏、对性能要求极高的人工智能(AI)和机器学习(ML)软件、自动驾驶汽车的组件、实时3D图形引擎、底层硬件驱动程序、完整的操作系统、网络设备的软件栈、网页浏览器等。C++程序很难与任何其他编程语言相匹配,因此,多年来,C++都是编写性能卓越、功能强大的企业级面向对象程序的事实标准语言。大型科技公司,如微软、Facebook、亚马逊、谷歌等,使用用 C++编写的服务来运行其基础设施。尽管C++语言已经风靡全球,但这种语言难以完全掌握。专业C++程序员使用一些简单但高效的技术,这些技术并未出现在传统教材中;即使是经验丰富的C++程序员,也未必完全了解C++中某些很有用的特性。
编程书籍往往重点描述语言的语法,而不是语言在真实世界中的应用。典型的C++教材在每一章中介绍语言中的大部分知识,讲解语法并列举示例。本书不遵循这种模式。本书并不讲解语言的大量细节并给出少量真实世界的场景,而是教你如何在真实世界中使用C++。本书还会讲解一些鲜为人知的让编程更简单的特性,以及区分编程新手和专业程序员的编程技术。
读者对象
就算使用C++已经多年,你仍可能不熟悉C++的一些高级特性,或仍不具有使用这门语言的全面能力。也许你编写过实用的C++代码,但还想学习更多有关C++中设计和良好编程风格的内容。也许你还不太了解最新版本 C++23 中引入的所有新特性。也许你是C++新手,想在入门时就掌握“正确”的编程方式。本书能满足上述需求,将你的C++技能提升到专业水准。
因为本书专注于将你从对C++具有基本或中等了解水平蜕变为一名专业C++程序员,所以本书假设你对该语言具有一定程度的认识。第1章涵盖C++的一些基础知识,可以当成复习材料,但是不能替代实际的语言培训和语言使用手册。如果你刚开始接触C++,但有十分丰富的C、Java或C#语言经验,那么应该能从第1章获得所需的大部分知识。
不管属于哪种情况,都应该具有很好的编程基础。应该知道循环、函数和变量。应该知道如何组织一个程序,而且应该熟悉基本技术,例如递归。应该了解一些常见的数据结构(如队列)及有用的算法(如排序和搜索)。不需要预先了解有关面向对象编程的知识——??这是第5章讲解的内容。
你还应该熟悉开发代码时使用的编译器。稍后将简要介绍Microsoft Visual C++和GCC这两种编译器。要了解其他编译器,请参阅编译器自带的指南。
本书主要内容
阅读本书是学习C++语言的一种方法,通过阅读本书既能提升编码质量,又能提升编程效率。本书贯穿对C++23新特性的讨论。这些新的C++特性并不是独立在某几章中,而是穿插于全书,在有必要的情况下,所有例子都已更新为使用这些新特性。
本书不仅讲解C++语法和语言特性,还强调编程方法论、可重用的设计模式以及良好的编程风格。本书讲解的方法论覆盖整个软件开发过程——从设计和编码,到调试以及团队协作。这种方法可让你掌握C++语言及其独有特性,还能在大型软件开发中充分利用C++语言的强大功能。
想象一下有人学习了C++的所有语法但没有见过一个使用C++例子的情形。他所了解的知识会让他处于非常危险的境地。如果没有示例的引导,他可能认为所有源代码都要放在程序的main()函数中,还可能认为所有变量都应该为全局变量——??这些都不是良好的编程实践。
专业的C++程序员除了理解语法外,还要正确理解语言的使用方式。他们知道良好设计的重要性、面向对象编程的理论及使用现有库的最佳方式。他们还开发了大量有用的代码并了解可重用的思想。
通过阅读和理解本书的内容,你也能成为一名专业的C++程序员。你在C++方面的知识会得到扩充,将接触到鲜为人知和常被误解的语言特性。你还将领略面向对象设计,掌握卓越的调试技能。最重要的或许是,通过阅读本书,你的头脑中有了大量“可重用”思想,可将这些思想贯彻到日常工作中。
有很多好的理由让你努力成为一名专业的C++程序员,而非只是泛泛了解C++。了解语言的真正工作原理有助于提升代码质量。了解不同的编程方法论和过程可让你更好地和团队协作。探索可重用的库和常用的设计模式可提升日常工作效率,并帮助你避免白费力气去做重复的工作。所有这些学习课程都在帮助你成为更优秀的程序员,同时成为更有价值的雇员。
本书结构
本书包括6部分。
第I部分“专业的C++简介”是C++基础速成教程,能确保读者掌握C++的基础知识。在速成教程后,该部分深入讨论字符串和字符串视图的使用,因为字符串在示例中应用广泛。该部分的最后一章介绍如何编写清晰易读的C++代码。
第II部分“专业的C++软件设计”介绍C++设计方法论。你会了解设计的重要性、面向对象方法论和代码重用的重要性。
第III部分“C++编码方法”从专业角度概述C++技术。你将学习在C++中管理内存的最佳方式,如何创建可重用的类,以及如何利用重要的语言特性,例如继承。你还会学习输入输出技术、错误处理、字符串本地化和正则表达式的使用,学习如何利用模块组织可重用的代码。该部分还会讨论如何实现运算符重载,如何编写模板,如何使用概念限制模板参数,以及如何解锁lambda表达式和函数对象的功能。该部分还解释了C++标准库,包括容器、迭代器、范围和算法。在该部分你还将了解标准中提供的一些附加库,例如用于处理时间、日期、时区、随机数和文件系统的库。
第IV部分“掌握C++的高级特性”讲解如何最大限度地使用C++。该部分揭示C++中神秘的部分,并描述如何使用这些更高级的特性。在该部分你将学习如何定制和扩充标准库以满足自己的需求、高级模板编程的细节(包括模板元编程),以及如何通过多线程编程来充分利用多处理器和多核系统。
第V部分“C++软件工程”重点介绍如何编写企业级质量的软件。在这部分你将学习当今编程组织的工程实践,如何编写高效的C++代码,软件测试概念(如单元测试和回归测试),C++程序的调试技术,如何在自己的代码中融入设计技术、框架和概念性的面向对象设计模式,跨语言和跨平台代码的解决方案等。
第VI部分是四个附录。附录A列出在C++技术面试中取得成功的指南,附录B是带注解的参考文献列表,附录C总结C++标准中的头文件,附录D简要介绍UML(Unified Modeling Language,统一建模语言)(附录A~D可通过扫描封底二维码获取)。
本书没有列出C++中每个类、方法和函数的参考。Peter Van Weert和Marc Gregoire撰写的C++17 Standard Library Quick Reference是C++17标准库提供的所有重要数据结构、算法和函数的浓缩版。附录B列出了更多参考资料。下面是两个很好的在线参考资料。
cppreference.com
可使用这个在线参考资料,也可下载其离线版本,在没有连接到互联网时使用。
cplusplus.com/reference/
本书正文中提到“标准库参考资料”时,就是指上述C++参考资料。
下面是其他的优质在线资源:
github.com/isocpp/CppCoreGuidelines
《C++核心指南》由C++语言发明人Bjarne Stroustrup牵头撰写。指南的目的是帮助人们有效地使用现代C++。这些指导方针侧重于较高级别的问题,如接口、资源管理、内存管理和并发。
github.com/Microsoft/GSL
这是微软的指南支持库(GSL)的一个实现,它包含了C++核心指南使用的函数和类型。这是一个只有头文件的库。
isocpp.org/faq
这是一个频繁被提问的C++问题的庞大集合。
stackoverflow.com
可以在这里搜索常见编程问题的回答,或者提出你自己的问题。
使用本书的条件
要使用本书,只需要一台带有C++编译器的计算机。本书只关注C++中的标准部分,而没有任何编译器厂商相关的扩展。
任何C++编译器
可使用任意C++编译器。如果还没有C++编译器,可下载一个免费的。这有许多选择。例如,对于Windows,可下载Microsoft Visual Studio Community Edition,这个版本免费且包含Visual C++;对于Linux,可使用GCC或Clang,它们也是免费的。
下面将简要介绍如何使用Visual C++和GCC。可参阅相关的编译器文档了解更多信息。
编译器与C++23功能支持
本书包含C++23标准引入的新功能。在撰写本书时,还没有编译器可以完全支持C++23的所有新功能。某些新功能仅由某些编译器支持,而其他编译器不支持,而有些功能尚不受任何编译器支持。编译器厂商正在努力支持所有新功能,我相信不久就会有完全符合C++23标准的编译器可用。可以在en.cppreference.com/w/cpp/compiler_support上查看哪些编译器支持哪些功能。
编译器与C++模块支持
在撰写本书时,还没有编译器可以完全支持C++的模块。不过,所有主流编译器至少部分支持。本书在各个地方都使用了模块。如果你的编译器尚不支持模块,可以将模块代码转换为非模块代码,具体方法在第11章中有简要说明。
示例:Microsoft Visual C++ 2022
首先需要创建一个项目。启动Visual C++ 2022,在欢迎界面上,单击Create A New Project按钮。如果没有出现欢迎界面,单击File | New | Project。在Create A New Project对话框中,使用C++、Windows和Console标签,找到Console App项目模板,然后单击Next按钮。指定项目的名称、保存位置,单击Create按钮。
加载新项目后,就会在Solution Explorer中看到项目文件列表。如果这个停靠窗口不可见,可选择View | Solution Explorer。一个新创建的项目会包括一个名为.cpp的文件,就在Solution Explorer中Source Files部分的下方,可以在该文件中开始编写C++代码。如果想要编译源代码文件(扫描封底二维码获取本书源代码压缩文件),则必须在Solution Explorer中选择.cpp文件并将其删除。在Solution Explorer中右击项目名,再选择Add | New Item 或Add | Existing Item,就可以给项目添加新文件或已有文件。
在撰写本书期间,Visual C++ 2022尚未自动启用C++23功能。要启用C++23功能,可在Solution Explorer窗口中右击项目,然后单击Properties。在Properties窗口中,选择Configuration Properties | General,根据使用的Visual C++版本,将C++ Language Standard选项设置为ISO C++23 Standard或Preview | Features from the Latest C++ Working Draft,并单击OK按钮。
最后,使用Build | Build Solution编译代码。没有编译错误后,就可以使用Debug | Start Debugging运行了。
注意:
Microsoft Visual C++完全支持模块,包括 C++23 标准中的命名模块std。
示例:GCC
用自己喜欢的任意文本编辑器创建源代码,保存到一个目录下。要编译代码,可打开一个终端,运行如下命令,指定要编译的所有.cpp文件:
g++ -std=c++2b -o [source2.cpp ...]
-std=c++2b用于告诉GCC启用对C++23功能的支持。当GCC完全兼容C++23后,这个选项将改为-std=c++23。
模块支持
在 GCC 中,使用-fmodules-ts选项可以启用对模块的支持。
在撰写本书时,GCC 尚不支持 C++23 标准中引入的命名模块std(在第 1 章中介绍)。为了使这类代码能够编译,你需要将import std声明替换为单个标准库头文件的import声明。完成替换后,对于标准库头文件的import声明(例如以下内容),你需要对它们进行预编译:
import ;
这是一个预编译的示例:
g++ -std=c++2b -fmodules-ts -xc++-system-header iostream
例如,第 1 章中的 AirlineTicket 代码使用了模块。为了使用 GCC 编译它,首先将 std::println() 替换为 std::cout,因为在撰写本书时,GCC 尚不支持 功能。之后,将 import std; 声明替换为适当的 import 声明,在这个例子中是 和 。你可在可下载的源代码归档中的 Examples\Ch00\AirlineTicket 目录中找到已适配的代码。
接下来,编译标准库头文件和:
g++ -std=c++2b -fmodules-ts -xc++-system-header iostream
g++ -std=c++2b -fmodules-ts -xc++-system-header string
编译模块接口文件:
g++ -std=c++2b -fmodules-ts -c -x c++ AirlineTicket.cppm
最后,编译应用代码:
g++ -std=c++2b -fmodules-ts -o AirlineTicket AirlineTicket.cpp
AirlineTicketTest.cpp AirlineTicket.o
当其通过编译后,你可以这样运行它:
./AirlineTicket
注意:
使用 GCC 编译 C++ 代码时,采用 C++ 模块的过程可能在未来发生变化。同时,C++23 标准中的命名模块 std 将得到支持。届时,请查阅 GCC 文档,了解如何编译此类代码的更新流程。
C++23的打印范围支持
第 2 章描述了你可以轻松地将标准库容器(如 std::vector)的整个内容打印到屏幕上。这是自 C++23 引入的新特性,在撰写本书时,并非所有编译器都已支持此功能。
例如,第 2 章解释了你可以按如下方式输出 std::vector 的内容。如果你还不理解所有语法,没关系,到第 2 章结束时你就会掌握。
std::vector values { 11, 22, 33 };
std::print("{:n}", values);
这将输出:
11, 22, 33
如果你的编译器尚不支持使用 std::print() 打印容器内容的 C++23功能,你可将代码的第二行改为以下内容:
for (const auto& value : values) { std::cout
这将输出:
11, 22, 33
同样,如果你现在还不理解语法,别担心,到第 2 章结束时一切都会变得清晰。
配套下载文件
读者在学习本书中的示例时,可以手动输入所有代码,也可使用本书附带的源代码文件。然而,我建议手动输入所有代码,这对于学习和你的记忆都是有益的。本书使用的所有源代码都可以扫描封底二维码下载。
下载代码后,只需要用自己喜欢的解压缩软件进行解压缩即可。
另外,读者可扫描封底二维码,下载本书附录(附录A~D)和本书习题答案。