C++ 核心机制与内存管理
面向对象与面向过程
面向过程编程更关注解决问题的步骤,将程序视为一系列函数或过程的组合。每个函数完成具体任务,数据在函数间传递。
面向对象编程 (OOP) 则关注如何将现实事物抽象为对象。对象包含数据(属性)和操作数据的方法。思想是将数据和操作封装在一起,通过对象交互实现功能。
三大特性
- 封装:数据和操作封装在对象内部,外部只能通过接口访问。
- 继承:新类可继承并扩展原有类的属性和方法。
- 多态:不同对象对同一方法做出不同响应,增强灵活性。
简单来说,面向过程是把程序看作由函数组成的过程,而面向对象则是将元素视为对象。
C 语言与 C++ 的区别
- 头文件:C 语言常用
.h,C++ 虽兼容但推荐使用标准库头文件。 - 布尔类型:C99 之前无布尔类型,用 0 表示假,非 0 表示真;C++ 内置
bool类型。 - 编译器效率:C++ 因支持更多高级特性,编译开销略高于 C,但提供了更强的抽象能力。
- 语言定位:C++ 不是更好的 C,而是基于 C 的另一种语言。它包含 C 的特性,同时支持面向对象,易于维护、复用和扩展。
- 重载:C 语言不支持函数重载,C++ 支持。重载指同一作用域下函数名相同但参数类型、个数或顺序不同。C++ 编译器通过修饰函数名来区分重载函数。
C++ 编译过程
编译流程分为四个阶段:预处理、编译、汇编、链接。
- 预处理:处理
#开头的指令,如展开宏定义、插入头文件、删除注释。生成.i文件。 - 编译:将源代码转换为汇编代码,生成
.s文件。 - 汇编:将汇编代码翻译成机器指令的目标文件,如
.o或.obj。 - 链接:将所有目标文件和库文件连接成可执行文件(Windows 的
.exe或 Linux 的.out)。这一步解决了跨文件的符号引用问题。
多态详解
多态是面向对象的三大特征之一,指不同对象调用同一行为表现出不同形式。可以理解为'一个接口,多种实现'。
分类
- 静态多态:编译期间确定绑定,如函数重载、运算符重载、函数模板。
- 动态多态:运行期间确定绑定,通过虚函数重写实现,属于晚绑定机制。
虚函数
概念与底层
在基类函数名前加 virtual 关键字声明为虚函数。底层通过虚函数表(vtable)和虚表指针(vptr)实现。每个含虚函数的类都有一个虚函数表,存储所有虚函数地址。对象创建时初始化 vptr 指向对应的虚表。子类继承父类时会继承虚表,若重写虚函数则替换表中地址,从而实现运行时多态。
构造函数与析构函数
- 构造函数不能设为虚函数:对象创建时需先调用构造函数,此时虚表指针尚未建立,无法支持虚函数机制。
- 虚析构函数:建议将父类析构函数设为虚函数,确保通过基类指针删除对象时能正确释放子类资源。
重载、重写与隐藏
- 重载 (Overload):同一类中名字相同但参数不同的函数。用于处理类似任务。
- 重写 (Override):派生类重新定义基类虚函数,参数列表一致。用于提供新版本实现。
- 隐藏 (Hide):派生类定义同名的非虚函数,或参数列表不同,导致基类函数被隐藏。
引用与指针
引用
引用是变量的别名,创建时必须初始化且不可更改指向。
- 优势:不占额外内存,避免大对象拷贝开销;作为函数参数可避免指针解引用的复杂性;返回左值时可避免拷贝构造。
- 注意:引用不能为空,不能初始化为空对象。返回局部变量引用会导致悬空引用错误。
引用与指针区别
- 本质:指针是变量,存储地址;引用是别名。
- 可变性:指针可改变指向,引用一旦绑定不可更改。
- 访问方式:指针需解引用,引用直接访问。
- 多级:指针支持多级,引用不支持。
- 空值:指针可为空,引用不可为空。
- 运算:指针
++是地址偏移,引用++是值增加。
内存分区与管理
堆与栈
- 栈:自动管理,函数调用时分配,返回时释放。
- 堆:手动管理,使用
new/malloc申请,delete/free释放。
指针常量与常量指针
- 指向常量的指针 (
const int* p):指针可变,内容不可变。 - 常量指针 (
int* const p):指针不可变,内容可变。 - 指向常量的常量指针 (
const int* const p):指针和内容均不可变。
NULL 与 nullptr
- C 语言:
NULL通常定义为(void*)0。 - C++:
NULL定义为0。C++ 推荐使用nullptr,具有专门类型std::nullptr_t,类型安全且语义清晰。
new/delete 与 malloc/free
| 特性 | new/delete | malloc/free |
|---|---|---|
| 类型 | 运算符 | 库函数 |
| 返回值 | 正确类型指针 | void* |
| 构造/析构 | 自动调用 | 不调用 |
| 失败处理 | 抛出异常 | 返回 NULL |
| 重载 | 可重载 | 不可重载 |
- new 原理:先调用
malloc分配内存,再调用构造函数初始化对象。 - delete 原理:先调用析构函数清理资源,再调用
free释放内存。 - 数组释放:
delete[]会依次调用数组中每个对象的析构函数。
C++11 新特性
Lambda 表达式
Lambda 允许在代码中直接定义匿名函数,适合临时回调场景。它能捕捉外部变量,简化局部逻辑。但过于复杂的逻辑建议使用传统函数。
内联函数
使用 inline 关键字建议编译器将函数体直接插入调用处,减少函数调用开销。适用于简单、频繁调用的函数。递归函数通常不适合内联。
智能指针
C++ 没有垃圾回收机制,智能指针用于自动管理内存,防止泄漏。
- unique_ptr:独占所有权,不可复制,可通过
std::move转移所有权。 - shared_ptr:共享所有权,内部引用计数,最后一个销毁时释放内存。注意不要用一个原始指针初始化多个
shared_ptr。 - weak_ptr:弱引用,不增加引用计数,用于打破
shared_ptr循环引用。
函数模板
允许编写通用代码,避免为不同类型重复编写相似函数。编译器根据参数类型自动生成实例。STL 广泛使用模板实现容器和算法。需注意模板特化以处理特定类型的特殊逻辑。


