资讯动态

C++期末复习指南:从试卷真题反推指针、类与STL核心考点

发布时间:2026/9/17 9:58:58 来源:尧图企业网站定制
简介《C程序设计》期末考试试卷是面向东北林业大学计算机相关专业学生的高质量复习资料覆盖变量、数据类型、运算符、流程控制、函数、指针、数组与字符串、结构体、类与对象、继承多态、模板、STL、异常处理及文件I/O等核心考点既适合考前自测也可用于日常巩固。资源为PDF格式共1个文件大小约160KB排版紧凑、便于打印或移动端阅读。目前已有1002人学习下载从预览可以看出内容包含大量题干与注释能帮助使用者快速熟悉典型题型与解题思路。借助这份试卷备考者可在短时间内检验自身对C语法和面向对象编程的掌握程度并通过实战演练提升代码阅读与编写能力尤其适合期末冲刺阶段查漏补缺、针对性强化薄弱环节。1. 从一张东北林业大学 C 期末试卷反推复习主线一份期末试卷 PDF 拿到手多数人的第一反应是从第一题刷到最后一题。我的建议是先按题型和分值把知识点拆开再决定复习顺序。因为这类试卷的权重从来不是均匀的指针与数组、类与对象往往占掉 60% 以上的分值文件 I/O 和异常处理则集中在最后的大题里。东北林业大学这份《C 程序设计》期末试卷覆盖的正是 C 核心语法、面向对象、泛型与 STL、流操作四块内容。它适合两类人期末冲刺的在校生以及需要给新人做 C 基础摸底、想快速产出一套覆盖性考题的一线工程师。接下来我按试卷的典型命题结构把考点、代码和容易丢分的位置逐一拆开讲。2. 基础语法与函数指针传递、数组退化与作用域陷阱基础语法部分在试卷里通常以选择、填空和程序改错题出现占比约 25%。它看似送分实则是整张卷子区分度的起点因为很多丢分发生在变量生命周期、数组作为参数退化、字符串初始化方式这类细节上。2.1.1 内存模型sizeof 在数组和指针上行为不同#include iostream int main() { int arr[10]; int* p arr; std::cout sizeof(arr) \n; // 40 10 * 4 std::cout sizeof(p) \n; // 864 位平台指针固定 8 字节 return 0; }这段代码是笔试中非常高频的区分点。sizeof作用于数组时返回整个数组占用的字节数作用于指针时只返回指针本身的大小。试卷里常把它包装成“在函数内部打印数组长度”的题真正的问题在于数组作为函数参数传入后已经退化为指针函数内sizeof拿不到原始长度。常见做法是额外传入长度参数或者改用std::array与std::vector这也是 C 风格与现代 C 考题的重要分歧点。2.1.2 swap 的三种实现与引用传递void swap_by_value(int a, int b) { // 形参是副本改不到实参 int tmp a; a b; b tmp; } void swap_by_pointer(int* a, int* b) { // 传地址解引用后修改实参 int tmp *a; *a *b; *b tmp; } void swap_by_ref(int a, int b) { // 引用是别名直接操作原变量 int tmp a; a b; b tmp; }三种写法在试卷里对应三种不同的命题角度值传递不改变实参是指针和引用章节的引子指针传递需要调用方取地址、被调方解引用漏写任何一环都会改错值引用传递语法上最简洁但对新手来说容易忽略其修改实参的副作用。复习时建议把三种写法并排写一遍并留意形参为const int的场景例如std::string或自定义类型作为参数避免无谓拷贝这是性能题常见的考点。2.1.3 字符串初始化与只读区char s1[] hello; // 可修改栈上分配 6 字节 char* s2 hello; // 字符串字面量存储在只读区修改 s2[0] 是未定义行为 std::string s3 hello; // 堆上管理自动扩容试卷关于“c 字符串数组初始化”的题常见错误是把第二种写法当成普通字符数组去修改运行时报段错误。正确理解是char*指向的是编译期放在只读数据段的字面量char[]会拷贝到栈上。C 编程实践中优先使用std::string它管理内存、支持运算符重载也是 STL 容器算法能直接配合的前提。改错题里若看到char*指向字面量后又被写入基本可以直接判定为未定义行为。2.1.4 结构体对齐与内存布局#include iostream struct A { char c; // offset 0 int i; // 对齐到 4offset 4前面补 3 字节 double d; // 对齐到 8offset 8 }; // 总大小 16而不是 14813 #pragma pack(push, 1) struct B { char c; int i; double d; }; // 紧凑排布总大小 13 #pragma pack(pop)结构体对齐是选择填空题里最容易被忽略的知识点。sizeof(A)的结果取决于编译器按最大成员对齐的规则double对齐到 8 字节边界。试卷常考“计算结构体大小”或“调整成员顺序后体积如何变化”排序成员时把大类型放在前面能减少填充。#pragma pack在做网络协议解析和二进制文件结构体映射时有实际用途笔试中出现频率低但一旦出现就是压分项。3. 类与对象、继承与多态构造顺序、虚函数与深浅拷贝面向对象部分是本份试卷的核心分值占比通常接近 35%。选择题涉及访问控制和继承后的成员可见性编程题则集中在构造函数析构函数顺序、虚函数多态和资源管理上。3.1 构造与析构调用顺序#include iostream class Base { public: Base() { std::cout Base ctor\n; } virtual ~Base() { std::cout Base dtor\n; } }; class Derived : public Base { public: Derived() { std::cout Derived ctor\n; } ~Derived() override { std::cout Derived dtor\n; } }; int main() { Base* p new Derived(); delete p; // 输出顺序Base ctor - Derived ctor - Derived dtor - Base dtor }构造时先基类后派生类析构时先派生类后基类这个顺序考试必备。第二个关键点是基类析构函数必须声明为virtual否则通过基类指针delete派生类对象时只会调用基类析构派生类持有的堆资源会泄漏。这段代码同时解释了多态对象完整的生命周期试卷在程序阅读题里给出一段相关继承代码要求写出输出结果时顺序和 virtual 缺一不可。3.2 继承方式与成员访问属性基类成员public 继承protected 继承private 继承publicpublicprotectedprivateprotectedprotectedprotectedprivateprivate不可访问不可访问不可访问这张表是继承章节必考内容。出题形式通常是给出三类成员在各继承方式下的可见性让考生判断派生类外部能否访问。记忆方法是取基类成员访问级别和继承方式中更严格的级别private 成员永远只属于本类。复习时要结合代码验证不要只背结论比如 protected 成员在派生类成员函数中可访问但在外部不可访问这两个位置很容易混。3.3 虚函数表与抽象类class Shape { public: virtual double area() const 0; // 纯虚函数Shape 是抽象类 virtual ~Shape() default; }; class Circle : public Shape { double r; public: explicit Circle(double radius) : r(radius) {} double area() const override { return 3.14159 * r * r; } };抽象类无法实例化试卷常考“哪个类可以创建对象”这类判断。带纯虚函数的类作为接口存在派生类必须实现所有纯虚函数才能实例化否则派生类仍然是抽象类。底层机制上每个含虚函数的类有一个虚函数表对象里保存指向该表的虚表指针vptr运行时通过vptr查找实际函数地址。理解这个机制后就能解释为什么构造函数不能是虚函数、为什么析构函数建议声明为虚函数。3.4 深浅拷贝与拷贝构造函数class Buffer { int* data; size_t size; public: Buffer(size_t n) : size(n) { data new int[n](); } // 深拷贝重新分配内存并复制内容 Buffer(const Buffer other) : size(other.size) { data new int[size]; for (size_t i 0; i size; i) data[i] other.data[i]; } ~Buffer() { delete[] data; } };默认拷贝构造函数做的是逐成员浅拷贝两个对象会指向同一块data内存任一对象析构后另一个就变成悬挂指针。试卷里的程序改错题经常故意不写拷贝构造函数让考生指出 double free 问题。判断是否必须自定义拷贝构造的简单规则是类里有非智能指针管理的堆资源时一定需要深拷贝或将其替换为std::unique_ptr/std::shared_ptr。4. 模板、STL 与文件 I/O从推导规则到流操作这部分在试卷中的占比约 25%题型以读程序、填空、编程大题为主。热词中出现的“c流i/o”就在这里文件读写题通常是最后一题的组成部分。4.1 函数模板与显式实例化template typename T T max_of(T a, T b) { return a b ? a : b; } int main() { std::cout max_of(3, 5) \n; // 推导为 int std::cout max_of(3.14, 2.72) \n; // 推导为 double std::cout max_ofdouble(3, 2.5) \n;// 显式指定为 double }函数模板由编译器在调用点实例化同一份代码生成多个版本的函数。模板参数推导规则中普通参数T会自动推导但若返回值依赖模板参数且参数不提供推导依据就需要显式指定。试卷会考“模板函数能否重载”“何时需要写typename”这类概念注意类模板使用时要显式给出类型参数例如std::vectorint。4.2 容器选型与迭代器失效容器底层结构适用场景常见操作复杂度vector动态数组随机访问频繁、尾部插入push_back 均摊 O(1)list双向链表中间插入删除频繁insert/erase O(1)map红黑树有序键值查找find O(log n)unordered_map哈希表无序高效查找find 平均 O(1)试卷常要求根据需求选择容器比如需要按键排序用map只做快速查找用unordered_map。遍历并删除vector元素时删除元素会使该位置及之后的迭代器失效正确写法是配合erase的返回值std::vectorint v {1, 2, 3, 4, 5}; for (auto it v.begin(); it ! v.end(); ) { if (*it % 2 0) it v.erase(it); // erase 返回下一个有效迭代器 else it; }如果直接erase后还继续使用原迭代器自增行为未定义运行时可能崩溃。试卷中的容器题喜欢把这种错误隐藏起来考生需要识别“在遍历过程中修改容器”的危险点。4.3 常用算法与自定义排序std::vectorint nums {5, 2, 8, 1}; std::sort(nums.begin(), nums.end()); // 默认升序 struct Student { std::string name; int score; }; std::vectorStudent stu {{A, 90}, {B, 85}, {C, 95}}; std::sort(stu.begin(), stu.end(), [](const Student a, const Student b) { return a.score b.score; // 按分数降序 });sort的第三个参数是谓词C11 之后多用 lambda 表达。试卷中的编程题要求“按 score 降序分数相同按 name 升序”则需要在 lambda 里写完整比较逻辑。std::sort不保证稳定需要稳定排序时使用std::stable_sort。数值要求用二分查找时可以使用std::lower_bound它针对有序序列返回第一个不小于目标值的位置。4.4 异常处理与资源释放try { std::vectorint v(100000000000); } catch (const std::bad_alloc e) { std::cerr 内存分配失败: e.what() \n; } catch (const std::exception e) { std::cerr 标准异常: e.what() \n; } catch (...) { std::cerr 未知异常\n; }异常处理知识点中抛出的顺序和捕获范围是考试重点。应该先捕获具体异常再捕获std::exception基类最后才是省略号。注意异常安全性常与资源管理绑定函数中抛出异常时栈上对象会依次析构自动释放资源。这也是 C 实践中用 RAII 管理文件、锁、内存的原因在试卷里体现为“构造函数中分配资源、析构函数释放资源”的题目。4.5 文件 I/Ofstream 与状态判断#include fstream std::ofstream out(data.txt); // 默认覆盖写 if (!out) { std::cerr open failed\n; return 1; } out line1\n 42 \n; out.close(); std::ifstream in(data.txt); std::string s; int n; in s n; // 用 按空白符读取 while (std::getline(in, s)) { // 按行读 std::cout s \n; }文件操作先判断是否成功打开这是试卷改错题最常挖的坑。ifstream的operator与getline的读取风格不同前者以空白符分隔后者保留换行边界混用时注意残留的换行符。写入时使用ofstream的app模式可以追加而不是覆盖二进制文件则要显式指定std::ios::binary。流的状态标志good()、fail()、eof()也可以单独设问读取结束时先判断eof再处理数据可避免最后一行被忽略。5. 运用试卷复盘法做考前一天自测编译选项、边界用例与运行环境用一张真题试卷做摸底的价值不在“背答案”而在通过编译器和边界用例找出自己的知识缺口。把这份 PDF 里的选择题改成程序填空题把你写错的选项改成代码去跑一遍比单纯看答案有效得多。g -stdc17 -Wall -Wextra -fsanitizeaddress,undefined -g main.cpp -o main-Wall -Wextra打开常见警告未初始化变量、有符号无符号比较都会暴露-fsanitizeaddress专门检测数组越界、堆溢出和 use-after-free换上它之后很多在笔试题里“看着对”的代码会直接报错。这是考前自测最重要的一个开关。针对手写代码题准备几个固定用例。二分查找用[1, 3, 3, 5]查3和4确认lower_bound语义判断质数用一个is_prime_sqrt优化版本遍历到sqrt(n)即可防止大数超时。冒泡排序题则手动加一个swapped标志一旦本轮无交换就提前终止这也是试卷主观题里能给阅卷人留下印象的优化点。bool is_prime(int n) { if (n 2) return false; for (int i 2; i * i n; i) { if (n % i 0) return false; } return true; }Windows 环境下如果代码编译通过但运行直接闪退双击报0xc000007b错误多数原因是缺少 Microsoft Visual C Redistributable 运行库。在 VS Code 里配置 C/C 环境时装好 C/C 扩展后请确认编译器路径指向的是 MinGW-w64 或 VS Build Tools 中的cl.exe并检查launch.json的miDebuggerPath指向正确的gdb不要用 32 位调试器去调试 64 位程序这个不匹配同样会触发 0xc000007b。自测完记得把-fsanitizeaddress去掉再测一次性能因为插桩会明显拖慢运行速度留下的代码也千万不要带着 sanitizer 参数提交。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价