Skip to content

0.2 如何使用本书

Hi!很高兴你准备正式翻开这本书!在接下来的旅程中,咱们会从第一条 C++ 语句出发,逐渐认识变量、数组、指针、函数、类、模板、STL、并发以及现代 C++ 新特性。内容不少,但不必一看到目录就开始担心。你不需要在第一次阅读时记住每条规则,也不需要在进入下一章前把上一章背得滚瓜烂熟。

学习编程更像学习游泳:看懂动作只是第一步,真正的掌握一定发生在自己下水之后。本书负责把知识拆成能够逐级攀登的台阶,而你需要做的,是亲手运行代码、修改代码、观察结果,并在出错时尝试弄清楚发生了什么。

ABSTRACT

  • 零基础读者可以按照章节顺序学习;
  • 已有基础的读者可以按主题查阅,并利用章节总结查漏补缺;
  • 示例代码应当亲手运行、修改和重新实现;
  • 标有标准版本或“选读”的内容,可以根据当前阶段灵活安排;
  • 忘记语法时不必硬背,可以使用第 17 章附录快速查询。

0.2.1 先确定自己的阅读方式

不同读者来到这里时,手里的地图并不相同。本书不要求所有人保持完全一样的速度,可以根据自己的基础选择阅读方式。

完全零基础的读者

如果你从未接触过编程,建议从第 0 章开始,按照目录顺序阅读。前几章会解释程序、语句、变量、类型和编译过程,这些看起来基础,却决定了后续能否真正理解函数、类和内存。

第一次阅读时,遇到暂时难以消化的底层细节,可以先留下标记继续前进。只要能够说清楚示例在做什么,并能亲手运行和稍作修改,就已经达到了这一阶段的目标。等后面接触更多实际场景后,再回来阅读,许多概念会自然清楚起来。

接触过其他编程语言的读者

如果你已经会使用 Python、Java、JavaScript 或其他语言,可以较快浏览第 1 至第 3 章,但不要直接跳过类型、对象生命周期、指针和引用。C++ 与许多语言最大的差异,不只是语法,而是对象何时创建和销毁、资源由谁负责、值与引用怎样传递,以及未定义行为可能带来的后果。

建议把更多时间放在第 4、6、7、11、12 和 14 章。这些章节涉及复合类型、函数参数、类、RAII、移动语义、模板和 STL,是建立 C++ 思维方式的重要部分。

已经学过 C 或 C++ 的读者

如果你已经掌握基础语法,可以先阅读目录和各章总结,找出不熟悉的主题,再按需进入正文。第 11 至第 16 章适合系统整理现代资源管理、泛型编程、标准库、并发和新标准知识,第 17 章则可以直接作为日常速查工具。

TIP

跳读不等于只阅读自己已经会的部分。最有效的跳读,是先通过章节总结发现知识缺口,再回到对应小节补齐它。

0.2.2 全书可以分成哪些阶段

虽然全书按照章节连续编排,但学习时可以把它们看成几个阶段。

阶段 章节 主要目标
准备阶段 第 0 至第 2 章 认识 C++、准备开发环境、理解程序怎样编译运行
语言基础 第 3 至第 6 章 掌握类型、复合数据、流程控制和函数
面向对象 第 7 至第 10 章 学习类、继承、多态和运算符重载
资源与泛型 第 11 至第 12 章 理解内存、RAII、智能指针、移动语义和模板
标准库与并发 第 13 至第 15 章 使用 I/O、错误处理、STL、Ranges、线程和协程
现代 C++ 第 16 章 梳理 C++11 至 C++23,并学习追踪 C++26 和标准草案
查询与延伸 第 17 章 速查语法、构建调试、危险行为、术语和学习路线

前一阶段通常会为后一阶段准备词汇。例如,不理解引用和对象生命周期,就很难安全使用 Lambda 捕获、视图和并发任务;不了解类和析构函数,也不容易真正理解 RAII 与智能指针。因此,零基础读者不宜为了尽快看到“高级内容”而大段跳过基础章节。

0.2.3 一篇文章应该怎样学习

建议每次只完成一个清楚的小目标,不必用一天时间硬吞下一整章。阅读一篇文章时,可以按照下面的步骤进行。

第一步:先知道这一节解决什么问题

先浏览标题、章节说明和开头几段,弄清楚这一节为什么存在。不要一开始就急着记语法。如果不知道一个工具解决什么问题,即使把写法背下来,也很难在实际程序中想起它。

第二步:亲手输入并运行示例

不要只用眼睛确认“我看懂了”。亲手创建源文件、编译并运行代码。输入代码的过程会暴露许多阅读时容易忽略的细节,例如分号、括号、头文件、命名空间和类型不匹配。

如果本书提供了可直接运行的源代码,也建议先自己输入一个较短版本,再用仓库代码核对。复制能够节省时间,却不能完全替代亲手复现。

第三步:主动修改一个条件

程序成功运行后,至少改动一处:

  • 换一组输入数据;
  • 改变循环次数或判断条件;
  • 增加一个成员或函数参数;
  • 把按值传递改成引用,观察行为;
  • 故意输入边界值;
  • 预测输出后再运行验证。

“修改后为什么仍然正确”与“修改后为什么出错”,都会比重复运行原样代码带来更多收获。

第四步:关掉文章重新写一次

不要求逐字复原,只要能够重新写出核心结构,并解释每一部分的作用。如果卡住,可以回来看一眼,再继续写。需要查阅并不等于没有学会,真正重要的是逐渐减少对完整答案的依赖。

第五步:用自己的话做一个小结

尝试回答三个问题:

  1. 这一节的新概念是什么?
  2. 它解决了什么问题?
  3. 使用时最容易犯什么错误?

如果暂时答不完整,可以带着问题继续学习,再在章节总结处回来检查。

0.2.4 怎样阅读代码示例

阅读代码时,不要只盯着最终输出。可以按程序真正需要的顺序追踪:

  1. 包含了哪些头文件;
  2. 定义了哪些类型、函数和变量;
  3. 对象在什么位置创建;
  4. 数据通过值、指针还是引用传递;
  5. 分支和循环在什么条件下执行;
  6. 函数在何处返回;
  7. 对象与资源在什么时候销毁。

遇到指针、引用、视图、Lambda 捕获、线程或协程时,再多问一句:被使用的对象现在还活着吗?谁负责保证它继续存在? 这个习惯会帮助你避开大量看似神秘的错误。

示例为了突出当前知识点,通常会省略大型项目中的部分工程结构。它证明的是某项规则或写法,而不一定是可以原封不动搬进所有项目的最终架构。随着章节推进,前面较直接的实现也可能被后面的 RAII、智能指针、算法或现代接口替代。

0.2.5 怎样对待错误

代码编译失败并不意味着学习失败。恰恰相反,编译器正在指出你的理解与语言规则之间还有一处没有对齐。

遇到错误时,建议依次这样处理:

  1. 从第一条错误开始阅读,后面的错误可能只是连锁反应;
  2. 查看错误对应的文件和行号,同时检查上一行;
  3. 核对括号、分号、拼写、声明、类型和头文件;
  4. 把复杂表达式拆开,把程序缩小到最少代码;
  5. 打开编译器警告,不要只追求“勉强编译通过”;
  6. 程序崩溃或结果异常时,使用调试器和 Sanitizer;
  7. 修复后解释根因,而不只是记住“这样改就行”。

第 17.9 节集中整理了编译、链接和运行时错误,第 17.10 节介绍了调试器、警告与 Sanitizer。遇到问题时,可以先去附录查找固定排查流程。

请注意

不要养成看见错误就整段替换代码的习惯。一次只改一个有理由的地方,并观察错误信息怎样变化,才能知道真正修复了什么。

0.2.6 标准版本标记是什么意思

书中会标注 C++11、C++14、C++17、C++20 或 C++23。这表示某项语言或标准库功能从相应标准开始出现,并不表示标有新版本的内容一定更高级,也不表示旧功能已经不能使用。

例如,范围 for 从 C++11 开始,if constexpr 属于 C++17,Concepts 和 Ranges 属于 C++20,std::printstd::expected 属于 C++23。要编译这些示例,需要选择合适的语言模式:

g++ -std=c++20 main.cpp -o app

但开启 -std=c++23 只代表编译器进入对应语言模式,不保证配套标准库已经完整实现所有 C++23 组件。如果找不到 <print><expected><generator> 等头文件,应先检查编译器和标准库版本。

第 16 章会系统梳理现代 C++ 的演进,第 16.8 节介绍如何阅读提案和标准草案,第 17.13 节则提供标准版本与功能测试宏速查。

0.2.7 “选读”内容应该跳过吗

标为“选读”或明显超出当前阶段的内容,并不是不重要,而是它依赖的知识可能尚未完全出现。第一次阅读时可以先理解它要解决的问题和基本结论,不必立即掌握所有细节。

例如,在基础类型之后提前遇到运算符重载,可以先知道“运算符能够由自定义类型赋予合适行为”,等学完类和函数后再回来深入。C++23、模板元编程、协程和标准草案等内容也可以采用同样策略。

可以使用三种标记管理自己的进度:

  • 已掌握:能够独立写出并解释;
  • 能使用:需要查资料,但知道什么时候使用;
  • 待回看:目前只知道用途,细节留到后续。

真实开发中,大量知识长期处于“能使用”状态。这很正常,工具书和文档本来就是程序员工作的一部分。

0.2.8 如何使用提示框、脚注和章节总结

书中不同内容承担的作用并不完全一样:

  • 章节开头的蓝色提示框列出本章学习目标;
  • 普通提示框补充背景、建议或现代写法;
  • 警告提示框指出容易导致错误、未定义行为或兼容性问题的内容;
  • 脚注解释术语来源、标准版本和不宜打断正文的补充信息;
  • 章节总结负责把分散知识重新串成一条主线。

第一次学习时,建议阅读所有警告和脚注。复习时则可以先读章节总结,根据哪些段落无法清楚复述,再返回对应小节。不要把章节总结当成正文替代品,它更像一次知识体检。

0.2.9 第 17 章附录应该怎样使用

附录不是需要从头背到尾的最后一轮考试。它是一只随时可以打开的工具箱:

  • 忘记关键字、类型范围或字面量时,查 17.1 和 17.2;
  • 需要换算进制或查看 ASCII、Unicode 时,查 17.3 至 17.5;
  • 对运算符分组没有把握时,查 17.6;
  • 不知道该包含哪个头文件时,查 17.7;
  • 需要编译命令或 CMake 模板时,查 17.8;
  • 程序报错、崩溃或行为异常时,查 17.9 至 17.11;
  • 想整理代码习惯或确认标准支持时,查 17.12 和 17.13;
  • 混淆术语或准备继续深入时,查 17.14 和 17.15。

工具书最重要的价值不是让你记住每一页,而是让你知道答案大致在哪一页。

0.2.10 建议的学习节奏

学习时间不必很长,但最好保持连续。一个可行的节奏是:

  1. 用 20 至 40 分钟阅读一个小节;
  2. 用同样或更多时间运行和修改示例;
  3. 第二天不看原文,重新写出核心代码;
  4. 每完成一章,阅读总结并做一个小程序;
  5. 每隔几章回顾以前标记为“待回看”的内容。

如果某一节卡住很久,可以先确认它是否是后续内容的必要前提。必要前提应缩小问题、查阅附录或在评论区提问;选读细节则可以做标记后继续前进。学习节奏允许暂停,但不要让一次卡顿变成永久停止。

0.2.11 学会提一个容易解决的问题

当你需要向他人求助时,尽量提供:

  • 想实现的目标;
  • 实际发生的结果;
  • 完整的第一条错误信息;
  • 能够复现问题的最小代码;
  • 编译器、标准库、操作系统和语言标准版本;
  • 已经尝试过哪些排查方法。

相比“为什么不能运行”,这些信息能让别人更快理解问题,也能迫使你在提问前完成一次有价值的自我排查。本书网页版的评论区欢迎讨论,但请不要提交密码、密钥、私人路径和其他敏感信息。

0.2.12 最后给你的几条建议

不要把阅读速度当成学习成果,也不要拿自己和已经写过多年代码的人比较。今天独立解决一个编译错误,弄清一处悬空引用,或者终于明白为什么要使用 const,都是真实的进步。

请允许自己忘记,但不要允许自己在不理解时假装理解;请放心查阅资料,但尽量在得到答案后亲手验证;请勇敢尝试新写法,也要认真尊重编译器警告、对象生命周期和工具链限制。

你不需要等到“准备得非常充分”才开始写程序。读完下一节,创建一个源文件,写下代码,编译它,然后看看会发生什么。许多真正属于你的知识,正是在这一刻开始形成的。

Comments