第一部分:快速上手 —— 建立 C++ 基本语法与编程范式
第一部分快速上手 —— 建立 C 基本语法与编程范式目标在 2~3 天内掌握能独立编写简单 C 程序的核心语法同时养成「内存与性能」的工程意识。学习方法每学一个知识点立刻动手写几行代码验证并思考“这个特性在内存里发生了什么”。1.1 Hello World 与编译流程第一个程序cpp#include iostream // 预处理器指令引入输入输出库 int main() { // 程序入口操作系统调用此函数 std::cout Hello, C! std::endl; return 0; // 返回 0 表示成功 }编译与运行保存为hello.cpp编译使用 gbashg -stdc17 -o hello hello.cpp-stdc17指定 C 标准推荐用最新-o hello指定输出可执行文件名运行./helloLinux/Mac或hello.exeWindows编译的四个阶段本质理解预处理处理#include、宏等生成.i文件编译将预处理后的代码翻译为汇编语言生成.s汇编将汇编转为机器码生成.o目标文件链接将多个.o和库文件合并为最终可执行文件重点每个.cpp文件独立编译为.o再链接成可执行文件。头文件.h只是声明不参与编译。1.2 基础数据类型、变量与运算符基本内置类型类型字节常见范围备注bool1true/false任何非零值转为truechar1-128~127 或 0~255用于字符或小整数int4-2³¹ ~ 2³¹-1最常用整数float4约 1e-38 ~ 1e38单精度浮点double8约 1e-308 ~ 1e308双精度浮点默认void无无值用于函数无返回值注意char可能有符号也可能无符号取决于编译器若需明确用signed char/unsigned char。变量声明与初始化cppint a 10; // 拷贝初始化 int b(20); // 直接初始化 int c{30}; // 列表初始化C11更安全防止窄化转换 auto d 3.14; // auto 自动推导为 double const int e 100; // 常量不可修改auto的本质auto是编译期类型占位符编译器根据初始化表达式推导出实际类型生成的代码与显式写出类型完全相同无运行时开销。运算符算术 - * / %整数除法取整%仅整数关系 ! 逻辑 || !短路求值位运算 | ^ ~ 操作二进制位赋值 - * /自增/自减 --前缀先变后用后缀先用后变1.3 流程控制与函数条件语句cpp// if-else int score 85; if (score 90) { std::cout A; } else if (score 80) { std::cout B; } else { std::cout C; } // switch仅整型/枚举 switch (grade) { case A: std::cout Excellent; break; case B: std::cout Good; break; default: std::cout Try harder; }循环cpp// for 循环经典 for (int i 0; i 10; i) { std::cout i ; } // while 循环 int n 5; while (n 0) { std::cout n--; } // 基于范围的 for 循环C11配合容器 int arr[] {1, 2, 3}; for (int x : arr) { std::cout x; }函数cpp// 函数重载同名不同参数 int max(int a, int b) { return (a b) ? a : b; } double max(double a, double b) { return (a b) ? a : b; } // 默认参数必须从右向左提供 void print(int x, int times 1) { for (int i 0; i times; i) std::cout x ; } // 内联函数建议编译器可忽略 inline int square(int x) { return x * x; }内联的本质inline只是向编译器发出请求希望将函数体在调用点展开以减少函数调用开销。但编译器会根据优化级别和函数大小决定是否内联。现代编译器在-O2下会自动内联简短函数。1.4 类与对象核心C 是面向对象语言类是用户自定义类型对象是类的实例。定义一个简单类cppclass Student { private: // 私有成员只能被类内部访问 std::string name; int age; public: // 公有接口 // 构造函数无返回值与类同名 Student(const std::string n, int a) : name(n), age(a) {} // 成员函数 void introduce() const { std::cout Im name , age years old.\n; } // 析构函数对象销毁时自动调用用于释放资源 ~Student() { // 一般在这里释放动态分配的内存但本例没有 } };使用对象cppint main() { Student s1(Alice, 20); // 栈上构造 s1.introduce(); Student* s2 new Student(Bob, 22); // 堆上构造需要手动 delete s2-introduce(); delete s2; // 务必释放 return 0; }RAII 思想资源获取即初始化本质利用对象的生命周期管理资源内存、文件句柄、锁等。资源在构造函数中获取在析构函数中释放。这样当对象离开作用域时资源自动释放即使发生异常也能保证释放这是 C 最核心的编程范式。示例如果我们使用std::fstream打开文件文件在析构时自动关闭无需手动close()。1.5 标准库入门C 标准库提供了丰富的数据结构和算法我们只需掌握最常用的几个。输入输出iostreamcpp#include iostream using namespace std; // 可省略 std::但不推荐在头文件或大型项目使用 int main() { int x; cout Enter a number: ; cin x; // 从键盘读入 cerr Error message; // 标准错误输出 return 0; }字符串std::stringcpp#include string std::string s1 Hello; std::string s2 World; std::string s3 s1 s2; // 拼接 std::cout s3.size() std::endl; // 长度字符数非字节 if (s1 Hello) { /* ... */ }容器 —— vector动态数组cpp#include vector std::vectorint v; // 空 vector v.push_back(10); // 尾部添加 v.push_back(20); v[0] 100; // 下标访问不检查越界 for (int i 0; i v.size(); i) { std::cout v[i] ; } for (int x : v) { // 范围 for std::cout x ; }vector 的简单本质vector是动态数组内部在堆上分配连续内存。当空间不足时它会重新分配一块更大的内存通常为当前容量的 2 倍或 1.5 倍将旧元素复制/移动到新内存然后释放旧内存。这个过程是自动的但需要注意迭代器失效问题插入/删除可能导致所有迭代器失效。容器 —— map关联数组cpp#include map std::mapstd::string, int scores; scores[Alice] 95; scores[Bob] 87; for (auto pair : scores) { // pair 是 std::pairconst std::string, int std::cout pair.first : pair.second std::endl; }map底层是红黑树平衡二叉搜索树按键有序插入/查找/删除复杂度 O(log n)。1.6 内存分区与变量生命周期重中之重为了深刻理解 C必须明白程序运行时内存如何划分。区域存储内容生命周期分配/释放栈Stack局部变量、函数参数、返回地址函数调用时分配返回时自动释放编译器自动管理速度极快堆Heap动态分配的对象new/malloc从new到delete由程序员控制手动管理速度慢可能产生内存碎片静态存储区全局变量、static变量程序启动分配结束释放编译器自动管理常量存储区字符串字面量、const全局常量程序启动到结束通常只读可能放在代码段示例分析cppint global 10; // 静态存储区 void func() { int local 20; // 栈 static int static_local 30; // 静态存储区只初始化一次 int* heap_ptr new int(40); // 堆 delete heap_ptr; // 必须手动释放 }关键理解栈上对象超出作用域自动调用析构函数堆上对象必须显式delete才会调用析构。忘记delete会导致内存泄漏。1.7 练习与巩固练习 1编写一个程序从标准输入读取两个整数输出它们的和、差、积、商整数除法。练习 2定义一个Circle类有半径radius成员提供计算面积和周长的成员函数。在main中创建对象并测试。练习 3使用vector存储 10 个随机整数可用rand()然后遍历输出并计算总和与平均值。思考题如果在函数内创建了一个vector对象当函数返回后这个vector占用的内存是否自动释放为什么提示RAII第一部分总结你已完成快速入门掌握了编译流程和基本语法类与对象的定义和使用以及 RAII 思想常用标准库组件内存分区和变量生命周期接下来我们将进入第二部分深入探讨 C 的内存模型、拷贝控制、移动语义、多态实现等本质原理。面试问“你如何理解 C 和 Java 的内存管理差异”回答框架C 提供手动和自动RAII两种方式性能可控且无垃圾回收开销Java 依赖垃圾收集器编程更简单但可能停顿。C 给予程序员更多控制权也要求更谨慎。