C++ 中的内存管理是一个核心知识点,涉及到程序的性能、稳定性以及资源管理能力。
一、C++ 内存划分(五大区域)
C++ 程序运行时的内存可大致分为以下几个区域:
| 区域 | 作用描述 |
|---|---|
| 栈区 | 函数调用时自动分配内存,存储局部变量、函数参数、返回值等 |
| 堆区 | 程序员手动 new/malloc 分配的内存,用于动态内存管理 |
| 全局区 | 存储全局变量、静态变量,程序开始时分配,结束时释放 |
| 常量区 | 存放常量字符串、const 修饰的全局常量等 |
| 代码区 | 存放程序的机器指令(函数代码),只读区域 |
示例说明:
#include <iostream>
using namespace std;
int g_val = 10; // 全局区
const int g_const = 20; // 常量区
int main() {
int a = 5; // 栈区
int* p = new int(100); // 堆区
const char* str = "hello"; // 常量区
delete p; // 手动释放堆区
return 0;
}
二、栈(stack)和堆(heap)的区别
| 属性 | 栈 | 堆 |
|---|---|---|
| 分配方式 | 编译器自动分配 | 程序员手动分配(new/delete) |
| 释放方式 | 自动释放 | 需要手动释放 |
| 空间大小 | 较小(一般几 MB) | 较大(受限于系统内存) |
| 分配效率 | 快,类似数据结构栈 | 慢,涉及系统调用 |
三、内存泄漏与野指针
内存泄漏(Memory Leak):
- 原因:申请了堆内存但没有释放。
void foo() {
int* ptr = new int(10); // 堆内存
// 没有 delete ptr,会导致内存泄漏
}
野指针(Dangling Pointer):
- 原因:指针指向已被释放的内存。
int* p = new int(5);
delete p;
*p = 10; // 未定义行为,p 是野指针
四、RAII 与智能指针管理内存
RAII(Resource Acquisition Is Initialization)是 C++ 管理资源的一种重要理念。
使用 std::shared_ptr、std::unique_ptr 示例:
#include <memory>
void use_smart_pointer() {
std::shared_ptr<int> sp = std::make_shared<int>(100); // 自动释放
std::unique_ptr<int> up = std::make_unique<int>(200); // 独占
}
智能指针的优点:
- 避免忘记释放内存
- 自动管理生命周期
- 减少内存泄漏风险
五、new/delete vs malloc/free
| 对比点 | new/delete | malloc/free |
|---|---|---|
| 语言 | C++ | C |
| 是否调用构造/析构 | ✅调用构造函数 | ❌不调用 |
| 类型安全 | ✅ | ❌(需手动强转) |
| 使用方式 | new T() / delete | malloc(sizeof(T)) / free |
六、内存对齐(补充)
- 编译器通常会对结构体按某种规则“对齐”,以提高访问效率。
- 可通过
#pragma pack控制对齐方式。
struct A {
char c;
int i;
};
默认情况下,A 可能不是 sizeof(char) + sizeof(int) 而是包含对齐填充。
七、调试与工具
检测内存问题的工具:
valgrind(Linux)Visual Leak Detector(Windows)ASAN(AddressSanitizer)- C++17 引入
std::pmr::memory_resource可进行自定义内存分配策略
609

被折叠的 条评论
为什么被折叠?



