# C++ 基础摸底小测验(10 题,预计 10 分钟) > 用途:验证 `docs/teaching/OUTLINE.md` §0 里"学员已掌握 C++ 基础语法与 OOP > 概念"这条假设是否成立。建议在 **Day1 模块 B 开始前**(C++ 回顾环节之前) > 发给学员,闭卷、不查资料,10 分钟内独立完成。 > > 题型:选择题 + 代码阅读(判断输出/找 bug)+ 1 道简答,覆盖 Day1 回顾要点 > 涉及的引用、重载、构造析构顺序、虚函数多态、运算符重载、模板、STL、 > const、深浅拷贝九个知识点。 --- ## 第 1 题(选择,30 秒) 下列关于"引用"和"指针"的说法,**错误**的是? A. 引用必须在定义时初始化 B. 引用可以为 `nullptr` C. 引用一旦绑定就不能再指向其他对象 D. 函数参数用引用可以避免拷贝开销 ## 第 2 题(代码阅读,1 分钟) ```cpp void f(int x) { std::cout << "int " << x; } void f(double x) { std::cout << "double " << x; } int main() { f(3.0f); } ``` 这段代码输出什么? ## 第 3 题(选择,30 秒) 关于虚函数,下列说法**正确**的是? A. 基类析构函数不加 `virtual`,通过基类指针 `delete` 派生类对象一定不会有问题 B. 构造函数可以是虚函数 C. 纯虚函数所在的类不能被直接实例化 D. 派生类必须重写基类的每一个虚函数 ## 第 4 题(代码阅读,1 分钟) ```cpp class A { public: A(){ std::cout<<"A"; } ~A(){ std::cout<<"~A"; } }; class B : public A { public: B(){ std::cout<<"B"; } ~B(){ std::cout<<"~B"; } }; int main(){ B b; } ``` 请写出输出的完整顺序。 ## 第 5 题(找 bug,1.5 分钟) ```cpp class Buffer { char* data; public: Buffer(int n) { data = new char[n]; } ~Buffer() { delete[] data; } }; void use() { Buffer a(10); Buffer b = a; // 用 a 拷贝构造 b } ``` `use()` 函数运行到结束时会发生什么问题?请说明原因。 ## 第 6 题(选择,30 秒) 关于函数模板,下列说法**正确**的是? A. 模板函数一旦定义,编译器就会为所有可能的类型生成代码 B. 编译器会根据调用时的实参类型自动推导模板参数,并生成对应的实例 C. 模板函数不能被重载 D. 调用模板函数时必须显式指定所有模板参数 ## 第 7 题(代码阅读,1 分钟) ```cpp std::vector v = {3, 1, 4, 1, 5}; for (int x : v) { if (x % 2 == 0) std::cout << x; } ``` 这段代码输出什么? ## 第 8 题(选择,30 秒) 下列哪个函数声明表示"这个成员函数不会修改对象的成员变量"? A. `void print()` B. `void print() const` C. `const void print()` D. `void const print()` ## 第 9 题(代码阅读,1 分钟) ```cpp class Point { public: int x, y; Point operator+(const Point& other) const { return Point{x + other.x, y + other.y}; } }; Point p1{1, 2}, p2{3, 4}; Point p3 = p1 + p2; std::cout << p3.x << "," << p3.y; ``` 这段代码输出什么? ## 第 10 题(简答,1.5 分钟) 用一两句话说明"深拷贝"和"浅拷贝"的区别,以及为什么一个类里如果有指针成员、 又没有自己实现拷贝构造函数,可能会引发问题。 --- ## 答案与评分(教师用,建议测验时不发给学员) | 题号 | 答案 | 对应知识点 · 出处 | |---|---|---| | 1 | B(引用不能为空,这是它和指针的关键区别之一) | 引用的本质 · `p01/ch03/reference_essence.cpp` | | 2 | `double 3`(`float` 到 `double` 是浮点提升,比 `float` 到 `int` 的转换更优先匹配 `f(double)`) | 函数重载决议 · `p01/ch03/function_overload_mechanism.cpp` | | 3 | C(A 错——没有 virtual 析构会导致派生类部分不被析构;B 错——构造函数不能是虚函数;D 错——不重写就继承基类实现,纯虚函数才必须重写) | 虚函数与抽象类 · `p01/ch04/s08` | | 4 | `A B ~B ~A`(先构造基类再构造派生类;析构顺序相反) | 继承中构造/析构顺序 · `p01/ch04/s07/inheritance_ctor_dtor_order.cpp` | | 5 | 浅拷贝:`b` 的 `data` 和 `a` 的 `data` 指向同一块内存;函数结束时 `~Buffer()` 被调用两次,对同一块内存 `delete[]` 两次(double free),行为未定义/可能崩溃 | 深拷贝 vs 浅拷贝 · `p01/ch04/s03/deep_vs_shallow_copy.cpp` | | 6 | B(模板是"按需实例化",不是提前生成所有版本) | 函数模板 · `p01/ch05/function_template.cpp` | | 7 | `4`(3,1,4,1,5 里只有 4 是偶数) | STL 容器与范围 for · `p01/ch09/s03/vector_iterator.cpp` | | 8 | B(`const` 放在参数列表后面,修饰的是"this 指向的对象不可修改") | const 成员函数 · `p01/ch04/s04/const_member_function.cpp` | | 9 | `4,6`(`1+3=4`,`2+4=6`) | 运算符重载 · `p01/ch04/s06/overload_assignment.cpp` | | 10 | 浅拷贝只复制指针本身(地址),深拷贝复制指针指向的内容;没有自定义拷贝构造函数时,编译器生成的默认拷贝构造函数是浅拷贝,两个对象的指针成员会指向同一块内存,析构时重复释放(double free)或修改一个对象的数据影响另一个对象 | 深拷贝 vs 浅拷贝 · `p01/ch04/s03/deep_vs_shallow_copy.cpp` | ### 评分建议 - **8–10 题正确**:具备 `OUTLINE.md` §0 假设的基础,按 Day1 模块 B 原定的 "巡礼式回顾"节奏推进即可。 - **5–7 题正确**:部分薄弱点——对照上表找出学员集中出错的知识点(比如普遍 在第 4/5 题失分,说明构造析构顺序和深浅拷贝没吃透),讲课时在对应知识点 多花 5–10 分钟,其余部分维持原节奏。 - **0–4 题正确**:明显达不到"已掌握 C++ 基础语法与 OOP 概念"的假设——按 `OUTLINE.md` §0 里的预案,Day1 模块 B 的讲授部分退回到语法讲解,练习任务 保持不变但预期完成度应下调,不需要重排整个教案结构。 ## 使用方式 - 建议纸质或线上表单均可,闭卷、不查资料、不讨论,10 分钟收卷; - 只用于摸底分层,不计入 `docs/TRAINING_PLAN_2026.md` 的正式考核成绩; - 大规模学员时可以只统计"每题正确率"而不用逐份细看,正确率低于 50% 的题 对应知识点在 Day1 模块 B 里适当加时。