pusidun
← All posts

侯捷 C++11/14 导读:从语言新机制走进标准库实现

侯捷 C++ 六门课总目录

会使用一个容器,与能解释它为什么需要某种语言机制,是两种不同的学习进度。这门课把它们接了起来:先认识参数包、列表初始化、类型推导和移动语义,再回到 tuple、容器和标准库源码,观察这些机制怎样协作。

来源卡:讲者侯捷;原课标题页为《C++2.0 新特性(C++11/14)》,画面带 Boolan 博览标识。本系列依据 B 站账号 DetachmentSy2025 年上传的《侯捷 - C++新标准C++11&14》(BV1wBh5zkE2Y)整理,核对日期为 2026-09-12。原始录制年份未核实,上传年份不代表授课年份。本文对应 P1《演进、环境与资源》。本次回放

这些是 AI 初加工的学习笔记:先读取完整音轨转录,再抽核关键课件与代码;不发布逐字稿。“现代补充”“整理者实验”与课堂演示分别标明。覆盖范围是当前上传的 31 个分P,不据此宣称原课无缺节或涵盖 C++14 的全部内容。

先修:能读旧代码,再解释新写法带来的变化

P1 首先限定了受众:需要已有 C++ 语法与语义基础。它会补讲某些必要概念,但不是从变量、指针开始的入门课。读这组文章前,最好能够解释类的构造与析构、按值传参与按引用传参、函数重载、模板参数,以及容器与迭代器的基本关系。

还不熟悉这些内容时,可先从六门课总目录中的面向对象课程进入。已有经验的读者则可以带一个具体问题来读:为什么 {3, 7} 有时是两个元素,有时是一次构造调用?为什么写了 std::move 仍然发生复制?为什么泛型包装函数不能直接把具名参数传下去?

这些问题要求同时理解语法与对象行为。只记“新标准增加了某个关键字”,不能回答它们。

为什么开头就讲可变参数模板

课堂没有严格按语法难度递增。P1 末尾解释了自己的安排:先用可变参数模板展示一项重要的新能力,再穿插较小的新特性,之后回到参数包的深入应用。

这是一种先看到用途、再逐步补足机制的路径。第一次见到 typename... Args 时,不必马上把递归继承、展开规则和完美转发一起吃透。先确定它解决的是“参数的数量与类型组合可变”这个问题,再逐层观察它怎样成为库的实现工具。

同样,移动语义要回到资源所有权与容器扩容才有意义;lambda 要与比较器、算法及回调生命周期连在一起。后续文章按这些依赖组织,而不是每一个关键字单独写一篇词条。

编译器、语言模式与标准库是三个检查点

P1 的环境案例很具体:侯捷在 Dev-C++ 5.11 与 MinGW/GCC 4.9.2 环境中尝试新语法,发现编译失败;在项目选项的 Language Standard 中选定 ISO C++11 后,测试才按预期通过。

这里值得保留的不是历史菜单的点击顺序,而是排查顺序。编辑器或 IDE 的版本不能独自证明某项语法可用;它调用了哪个编译器、传入什么标准模式、链接哪套标准库,都可能影响结果。

整理者补充:在 GCC/Clang 的小实验中,把 -std=c++11-std=c++14 写进命令,比依赖本机默认值更容易复现。还要记录编译器版本。若测试的是库功能,仅仅语法通过也不够;需要包含正确头文件并验证相应库组件。GCC 的标准支持表可以用于核对具体版本与特性,而不能把课堂所说的“很新”沿用到今天。

__cplusplus 是线索,不是逐项能力证明

课堂打印 __cplusplus,观察 199711L201103L,并用它解释标准库源码中的条件编译。这是建立语言模式意识的好入口。C++14 对应的常用值是 201402L

课件本身已注明厂商可能提供不同宏值。不过,P1 口头根据 Visual Studio 2012 仍输出旧值,推测也许需要类似开关,这里必须保留其推测性质。现代修正:MSVC 长期保留 199711L 以兼容旧代码;/Zc:__cplusplus 从 Visual Studio 2017 15.7 才提供,用于让宏反映选定标准模式。不能把这个后来的选项套回 VS2012,也不能单凭旧值断言完全不支持 C++11。Microsoft 官方说明明确区分了报告宏值与选择语言标准。

读库源码时,先找职责,再找文件

P1 将新特性分成语言与标准库两部分。nullptr、参数包属于语言机制;arraytupleunordered_set 等通过标准库接口提供。使用后一类组件,需要包含相应头文件并使用 std:: 名字空间。

课堂随后演示了全文检索:把检索范围限定到编译器的 include 目录,查找 nullptr_t,从命中行找到文件,再打开完整上下文。这比在几百个头文件中逐个猜测有效,也让“想看看它怎么实现”变成可执行的步骤。

整理者补充:如今可以使用 IDE 跳转或 rg 完成同类工作;工具名并非学习目标。真正需要记录的是:正在读哪家标准库、哪个版本、哪个内部类型。实现中的类名、继承方式、成员布局与下划线辅助函数,可以解释该实现,却不自动成为用户程序能依赖的契约。

这条边界会贯穿后续 initializer_list、哈希表与 tuple 的分析。读到一个库类只保存指针和长度,应继续问它指向的数据由谁创建、谁管理生命周期,而不是立即照搬一份裸指针类。

一处历史名词修正:C++03 与 TR1

P1 的演化页把 C++03 与 TR1 放在一起,口头讲解也将两者联系得过紧。整理者修正:C++03 是语言与库标准的修订版本;TR1 是另行提出的库扩展技术报告,二者不能画等号。WG21 的 N1836 库扩展报告草案标为 2005 年,清楚表明这不是“2003 标准的另一个名字”。

同样,“C++2.0”是课程用于突出变化幅度的叫法,不是编译器 -std 选项。检索技术问题时,应使用 C++11、C++14 及具体特性名。课堂把二者合讲,文章则在完整示例中标明语言版本,避免把后来版本的简写混入 C++11 示例。

重点回看

讲次与时间 画面或讨论线索 回看重点
P1 · 01:08–02:58 语言/标准库、语法语义基础、实例测试 受众、范围与“较全面”而非无所不包的课程承诺
P1 · 11:50–13:33 DevC++ ISO C++11 开关 将 IDE、编译器与标准模式分开排查
P1 · 18:55–23:28 Windows Grep、include、nullptr 从关键词命中进入完整源码上下文
P1 · 24:20–27:45 __cplusplus、199711、201103 观察测试思路,同时对照本文 MSVC 修正
P1 · 27:45–29:38 重磅出击、Variadic Templates 为什么采用先预览重要能力、再回来深入的路径

时间以此上传版 SRT 与抽核画面对齐;区间用于定位讨论,不意味着每一秒都有可读代码。

带着可验证的问题继续读

  1. 对同一份只打印 __cplusplus 的程序,分别用 C++11 与 C++14 模式编译。记录完整命令、版本和输出;若输出不符合预期,先检查实际调用的工具链,而不是修改程序让输出“看起来正确”。
  2. 找到本机 std::initializer_list 的定义,记录实现与版本。先列出接口,再把内部字段另列一栏,检验哪些结论换一家标准库仍应该成立。
  3. 阅读本站折叠表达式旧文时,先比较它如何把一串参数归约为一个表达式。待读过本系列参数包篇,再用减法检验左右结合方向;这里连接的是 C++11 递归展开到 C++17 折叠表达式的变化,不能把 C++17 写法直接算作本课语法。