Lecture 1 (Week 1 - Tuesday): 欢迎与课程概览 (Welcome!)
Lecture 1 (Week 1 - Tuesday): 欢迎与课程概览 (Welcome!)
概述
本讲是 CS106L(Stanford 的《Standard C++ Programming》,Spring 2026,教学语言为现代 C++,覆盖 C++26)的开篇课:讲师自我介绍、课程定位与评分方式,并用大量真实案例回答”为什么要学 C++”。核心内容包含三块:C++ 的历史与设计哲学(Readable、Safety、Efficiency、Abstraction、Programmer Choice 五大支柱)、”同一段 Hello World 在 C++ 中可以有汇编层 / C 层 / 现代 C++ 层三种写法”的语言分层观,以及整个学期的知识地图。
本讲没有新语法,但建立了一个贯穿全课程的心智模型:C++ 是编译型、静态类型的语言,既追求效率又追求代码的优雅与可读性。课程以现代标准(C++11 之后直至 C++26)为教学语言,全部作业只使用标准库(STL)——不依赖 Stanford 自制库。最后一部分是课程后勤:讲座时间与签到、8 个每周作业、S/NC 评分规则与联系方式,务必记牢。
核心特性与语法详解
本讲是概念课,这里把”核心特性”理解为支撑后续所有讲座的语言世界观与基本构件。
- C++ 设计哲学(Bjarne Stroustrup 的五大原则)
- 定义与目的:这是理解 C++ 一切设计的钥匙——为什么 C++ 有那么多”看上去很麻烦”的规则。
- 核心内容:
- Express ideas and intent directly in code(直接在代码中表达思想与意图);
- Enforce safety at compile time whenever possible(尽可能在编译期强制安全);
- Do not waste time or space(不浪费时间和空间——零开销原则);
- Compartmentalize messy constructs(把丑陋的细节封装隔离,如内存管理);
- Allow the programmer full control, responsibility, and choice(把控制权、责任与选择权交给程序员)。
- 设计意图与最佳实践:Bjarne 的名言 “Code should be elegant and efficient; I hate to have to choose between those” 是课程灵魂——后续每讲(类型、引用、模板、移动语义……)都可以用这五条来解释”为什么语言要这样设计”。
- C++ 的三种”合法程序”(语言分层观)
- 定义与目的:同一个任务,C++ 里可以写出汇编级、C 级、现代 C++ 级三种代码,且全部合法。这体现了 C++ 对 C 的向后兼容(backwards compatible)以及”程序员选择权”。
- 核心语法:现代 C++ 版
auto str = std::make_unique<std::string>("Hello World!");;C 版printf("%s", "Hello, world!\n");;汇编版asm("...");内联汇编。 - 设计意图与最佳实践:你写的是哪一层,取决于需求(性能关键区 vs 业务逻辑)。CS106L 教的是现代 C++ 层——安全、可读、高效三者的平衡点。
- 现代 C++ 的几大语言构件(本讲先”混个脸熟”)
- 定义与目的:幻灯片用一行 Hello World 串起了本课程的核心主题。
- 核心语法:
- 流与运算符重载:
std::cout << *str << std::endl; - 模板与类型推导:
std::make_unique<std::string>(...)、auto - 智能指针:
std::unique_ptr(RAII,自动管理内存) - 命名空间:
std::前缀
- 流与运算符重载:
- 设计意图与最佳实践:这些构件将在第 3 讲(初始化与引用)、第 4 讲(流)、第 11-12 讲(智能指针)逐一展开,本讲只需认识它们的”长相”。
- C++ 标准演进史(C++98 → C++26)
- 定义与目的:C++ 自 1979 年起步、1985 年首次发布,至今仍是 TIOBE 前三的语言;标准委员会每三年修订一次标准。
- 核心内容:1979(前身)→ 1983(C++ 诞生)→ 1998(C++98 首次标准化)→ 2003(C++03)→ 2011(C++11,现代 C++ 起点)→ 2014 → 2017 → 2020 → 2023 → 2026(We are here!)。
- 设计意图与最佳实践:本课程以 C++11 之后(含 C++26 新特性)的”现代 C++”为教学语言;编译时通常用
-std=c++20或更新标准。
- C++ 与 C 的历史关系
- 定义与目的:1972 年 Dennis Ritchie 创造 C(快、简单、跨平台),但缺少对象/类、泛型/模板能力,写大型程序繁琐;1983 年 Bjarne Stroustrup 在 C 的基础上创造了 C++,目标是快 + 简单 + 跨平台 + 高层特性。
- 设计意图与最佳实践:理解”汇编的缺点 → C 的诞生 → C 的缺点 → C++ 的诞生”这条演进线,就知道 C++ 为什么”既要效率又要抽象”。
- 编译型语言的执行模型(预告)
- 定义与目的:C++ 是编译型语言:编译器先把整个程序翻译成机器码打包成可执行文件,再运行;因此有”编译期(compile time)”与”运行期(run time)”两个阶段。错误尽可能在编译期被发现(详细对比见 Lecture 2)。
- 设计意图与最佳实践:越早发现错误成本越低——这是”编译期强制安全”哲学的体现。
- 为什么 C++ 无处不在(”The invisible foundation of everything”)
- 定义与目的:幻灯片列举了大量 C++ 的真实应用场景,回答”为什么值得学”。
- 核心内容:游戏(Valorant、CS:GO/CS2)、高频交易、自动驾驶、Arduino 嵌入式、GPU 编程、数据库(MySQL、MongoDB)、浏览器(Chrome、Safari、Edge)、虚拟现实(Quest)、底层 ML 框架(PyTorch、TensorFlow)、编译器与虚拟机(JVM、LLVM、GCC)、操作系统(Windows、macOS、Linux)。
- 设计意图与最佳实践:C++ 擅长处理大量数据、且处理得非常高效、同时保持代码优雅可读;学完 CS106L 后,CS111(操作系统)、CME213(并行计算)、CS143(编译器)、CS144(网络)、CS248A(图形学)、MUSIC256A 等课程都会直接用到 C++。
- 本课程的知识地图(Topics We’ll Cover)
- 定义与目的:幻灯片给出了整个学期的路线图,帮助你建立全局观。
- 核心内容:欢迎 → 类型与结构体 → 初始化与引用 → 流 → 容器 → 迭代器与指针 → 类 → 高级类 → 模板 → 高级模板 → 函数与 lambda → 运算符重载 → 特殊成员函数 → 移动语义 →
std::optional与类型安全 → RAII、智能指针 → C++ 项目实践。 - 设计意图与最佳实践:每讲都有明确的前置依赖(如”移动语义”依赖”特殊成员函数”),按顺序跟进即可;本讲之后的第 2、3 讲(类型与结构体、初始化与引用)是全部内容的语法地基。
- CS106L 与 CS106B 等课程的定位差异
- 定义与目的:CS106B 等课关注抽象、递归、指针等概念,只用 C++ 的最小集合并重度依赖 Stanford 自制库;CS106L 关注代码本身:只用标准库(STL),理解”好代码长什么样、C++ 为什么这样设计”。
- 设计意图与最佳实践:CS106L 是 1 学分的”轻松”课程(S/NC 评分),但内容密度高;把注意力从”解决问题”转向”把解决方案写得优雅、正确、高效”。
- 课程后勤要点速览(Course Logistics)
- 定义与目的:课堂公布的管理规则,直接影响你的学分,值得抄进笔记。
- 核心内容:
- 讲座:每周二、四 15:00–16:20,Thornton 110;讲座不录像;从第 2 周起每次开讲有 1-2 道签到小测,每人有 2 次免签到额度;签到二维码只出现在前 10 分钟幻灯片上;
- 生病/特殊情况:身体不适请留在家里并通过邮件/Ed 告知,绝不要求带病上课;
- Office Hours:第 2 周前公布(线下),欢迎来聊天提问;
- 作业:8 个每周小作业(每个 1-2 小时),周五发布、下周五截止,每人有 3 个免费晚交日;
- 评分:S/NC(通过/不通过)——第 2 到第 9 周 14 次讲座中出勤 12 次 + 完成全部 8 个作业,即可拿到 S;
- 联系方式:
cs106l-spr2526-staff@lists.stanford.edu(课程统一邮箱)、Ed 论坛(经 Canvas 加入)、课后或 OH 面谈。
- 设计意图与最佳实践:出勤与作业是硬指标,建议把”每讲扫码 + 每周五查作业”设为固定日程;有问题优先走 Ed 公开提问(他人也能受益)。
- 工具链与编译(Toolchain)
- 定义与目的:C++ 是编译型语言,写代码 → 编译 → 运行三步走;课堂上还用 godbolt.org 做了”编译器到底生成了什么汇编”的现场演示。
- 核心语法:
g++ -std=c++20 main.cpp -o main然后./main。 - 设计意图与最佳实践:A1 起所有作业都用这个流程;用
-std=c++20(本课程教学标准)而非默认的旧标准;想理解”为什么 C++ 高效”,可以去 godbolt.org 看你的代码对应的汇编。
代码示例与逐步解说(核心)
示例 1:现代 C++ Hello World(C++14,改写自课堂幻灯片)
#include <iostream>
#include <memory>
#include <string>
int main() {
// make_unique 返回一个 std::unique_ptr<std::string>
auto str = std::make_unique<std::string>("Hello World!");
std::cout << *str << std::endl; // 解引用智能指针,输出字符串
return 0;
}
// Prints "Hello World!"
代码做什么:
#include <memory>、<string>:引入智能指针与字符串类型;std::make_unique<std::string>("Hello World!"):在堆上构造一个std::string,返回管理它的std::unique_ptr;auto str = ...:让编译器从右侧表达式的类型推导出str的类型(std::unique_ptr<std::string>);*str解引用得到字符串,<<运算符把它送到标准输出,std::endl换行并刷新缓冲区;- 函数结束、
str析构时,智能指针自动delete堆内存——不需要手写delete。
特性机制解说:
std::unique_ptr是 RAII(Resource Acquisition Is Initialization)思想的典型代表:内存的释放绑定在对象的析构上,杜绝new/delete配对遗漏导致的内存泄漏;auto是编译期完成的类型推导,str的类型在编译时就固定为std::unique_ptr<std::string>(静态类型,不是 Python 式的动态类型);<<之所以能作用于自定义类型,靠的是运算符重载——标准库为std::ostream重载了针对各种类型的operator<<。
示例 2:同一程序的三层写法对比(C++98 兼容 / 现代 C++)
// ① C 风格(C++ 向后兼容 C,这是合法的 C++ 程序)
#include <cstdio>
int main() {
printf("%s\n", "Hello, world!"); // 调用的是 C 函数 printf
return 0;
}
// ② 现代 C++ 风格
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl; // 类型安全的流输出
return 0;
}
代码做什么:两段程序输出完全相同,但实现机制迥异——printf 依赖格式字符串与可变参数(类型错误在编译期检查很弱),std::cout << 则通过重载在编译期确定与类型匹配的输出函数。
特性机制解说:这是”C++ 是 C 的超集”的直接证据:printf、C 风格头文件、甚至内联汇编在 C++ 中都合法(幻灯片展示了一个用 asm(...) 写 Hello World 的极端例子)。这给了程序员选择权(设计哲学第 5 条),但也意味着 C++ 需要更强的自律——所以本课程强调类型安全与现代写法。
示例 3:现代 C++ 的”优雅 + 高效”小示例(C++11)
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> names = {"Valorant", "MySQL", "LLVM"};
// range-based for:C++11 起的新特性,遍历容器
for (const auto& name : names) {
std::cout << name << " is built with C++!" << std::endl;
}
return 0;
}
代码做什么:创建一个字符串向量,用 range-based for 遍历并逐行输出。
特性机制解说:
std::vector是标准库容器,自动管理动态数组内存;const auto& name表示”以常量引用方式读取每个元素”——不复制字符串(高效),同时保证不修改(安全)。这正是 Lecture 3 将要详细讲解的引用与 const 的提前亮相;- 这一行代码同时体现了五大设计哲学中的 Readable(可读)、Safety(const)、Efficiency(引用避免拷贝)。
示例 4:手动内存管理 vs RAII 智能指针(C++98 风格 vs 现代风格)
// ① C++98 风格:手动 new/delete,容易泄漏
#include <iostream>
#include <string>
int main() {
std::string* s = new std::string("Hello");
std::cout << *s << std::endl;
delete s; // 忘记 delete 或提前 return 都会泄漏
return 0;
}
// ② 现代风格(C++11/14):unique_ptr 自动管理,无需手动 delete
#include <iostream>
#include <memory>
#include <string>
int main() {
auto s = std::make_unique<std::string>("Hello");
std::cout << *s << std::endl; // 离开作用域时自动释放内存
return 0;
}
代码做什么:两段代码都在堆上创建字符串并输出,区别只在内存如何释放。
特性机制解说:
- ① 中一旦中间逻辑
return或抛出异常,delete永远执行不到,内存泄漏;程序员必须手工保证每条路径都释放——这正是 C++98 时代最普遍的 bug 来源; - ② 中
std::unique_ptr在析构时自动释放所拥有的堆对象(RAII),所有权转移、异常安全都由类型系统保证,代码更短且不可能”忘记释放”; - 这一对比就是设计哲学第 4 条”Compartmentalize messy constructs(封装丑陋细节)”的活教材——把内存管理的脏活交给库,程序员专注业务逻辑。
示例 5:基础输入输出——流的预告(C++11)
#include <iostream>
#include <string>
int main() {
std::string name;
std::cout << "What's your name? "; // 输出提示
std::cin >> name; // 从标准输入读取一个词
std::cout << "Welcome to CS106L, " << name << "!" << std::endl;
return 0;
}
// 输入:Ada → 输出:Welcome to CS106L, Ada!
代码做什么:先打印提示,再从键盘读取字符串,最后输出欢迎语。
特性机制解说:
std::cin是标准输入流,>>运算符从流中提取数据到变量——与std::cout <<方向相反;>>按空白分隔读取,只读一个词(想读整行要std::getline,Lecture 4 详讲);- 流(stream)是 C++ 标准库最重要的抽象之一,第 4 讲整讲展开;A1 读 CSV 文件就靠它。这一行
std::cin >> name就是”输入 → 程序 → 输出”最小闭环,也是你验证工具链的最佳练习。
与旧标准(如C++98)的对比
- C++98 时代没有
auto类型推导:auto在 C++98 中是存储类说明符(如auto int x = 1;),毫无用处;现代auto的推导语义是 C++11 才引入的。 - C++98 没有智能指针:必须手动
new/delete,一旦忘记delete或异常路径泄漏,就产生内存泄漏;std::unique_ptr(C++11)与std::make_unique(C++14)让”裸指针所有权”问题大幅减少。 - C++98 没有 range-based for、没有
nullptr、没有 lambda:遍历容器要写for (size_t i = 0; i < v.size(); ++i)或迭代器循环,代码更长、更容易出错。 - 标准演进节奏:C++98 后十年停滞(2003 只是小修补),直到 2011 年 C++11 带来”现代 C++”大爆炸;此后每三年一个版本(14/17/20/23/26)。本课程站在 C++26 的视角教学,但核心概念(引用、const、struct)从 C++98 就有,只是表达方式不断进化。
- 一个 C++98 时代的 Hello World 长这样:
// C++98 典型写法:无 auto、无智能指针、手动管理
#include <iostream>
#include <string>
int main() {
std::string* str = new std::string("Hello World!");
std::cout << *str << std::endl;
delete str; // 记得手动释放
return 0;
}
对比本讲示例 1 的现代写法:类型名改为 auto、堆对象交给 std::unique_ptr、无需 delete。功能等价,但现代版更短、更安全、更不易错——这就是”标准每三年进步一次”带来的实际收益。
关键要点
- C++ 的五大设计哲学:可读、安全、高效、抽象、程序员选择——这是解释一切语言特性的总纲。
- C++ 是编译型、静态类型的语言,编译期会尽可能多地发现错误,且运行效率高(”不浪费时间和空间”)。
- C++ 向后兼容 C,同一任务存在汇编/C/现代 C++ 多层写法;本课程只教现代 C++ 写法。
- C++ 标准每三年一版(C++98 → … → C++26),本课程以现代标准(覆盖 C++26)为教学语言。
- 课程产出:掌握 STL、理解”好代码长什么样”,培养类型安全、内存高效、const 正确的编码习惯——这正是 CS107/CS111 等后续课程与工业界的需要。
- C++ 应用遍布”看不见的地基”:操作系统、浏览器、数据库、游戏、自动驾驶、ML 框架、编译器——学它不是为了应试,而是为了能读懂和写出这个世界的基础设施。
常见陷阱与注意事项
- 忘记
std::前缀:cout、string都是std命名空间里的名字,不写std::且没有using namespace std;就无法编译;写using namespace std;虽省事,但会引入歧义(见 Lecture 2),是公认的坏风格。 - 忘记
#include对应头文件:用std::cout要#include <iostream>,用std::string要#include <string>,用std::unique_ptr要#include <memory>;头文件缺失的报错信息往往令人困惑。 - 用 C 风格习惯写现代 C++:如用
printf+ 裸指针 + 手动new/delete。不是不能编译,而是放弃了类型安全与 RAII 的保护。 - 混淆”合法”与”推荐”:内联汇编、C 风格写法在 C++ 中合法,但几乎从不是好选择;课程的评判标准是”现代、优雅、正确”。
- 以为
auto是动态类型:auto推导出的类型在编译期就固定,之后不能再改变(auto i = 1; i = "hello";是编译错误)——细节在 Lecture 2 展开。 - 误用
std::endl的时机:std::endl会刷新缓冲区(flush),在大量输出循环里用'\n'更快——”不浪费时间和空间”从这些细节开始。 - 忽略编译警告:编译器是你的朋友。养成读警告、
g++ -Wall -Wextra编译的习惯,很多运行期 bug 在编译期就有提示。
关联作业提示
None(本讲无作业)。课程有 8 个每周小作业(每次 1-2 小时),第一个作业(A1: SimpleEnroll)将在第 2 周周五发布。建议:
- 按 A1 说明完成编译器环境搭建(
g++ -std=c++20 main.cpp -o main),提前用上面的 Hello World 验证工具链; - 记住课程评分规则(S/NC:Week 2-9 期间出勤 12/14 次讲座 + 完成全部 8 个作业),每讲开头的签到二维码只在前 10 分钟有效;
- 把本讲”三层写法”的印象留着:A1 的全部代码都要求用现代 C++(struct、引用、流)完成,正是 Lecture 2、3 的内容;
- 可以现在就动手:把示例 1 的现代 Hello World 编译运行一遍,再试试示例 3 的 vector 遍历——工具链顺了,A1 上手就会非常快。
