栈内存由编译器自动管理,函数调用时压入、返回时弹出,用于存放局部变量等,分配释放极快但大小受限;堆内存需手动管理,用于运行时动态数据,易引发内存泄漏或崩溃;现代C++推荐优先使用栈和RAII智能指针替代裸new/delete。
栈空间用于存放局部变量、函数参数、返回地址等,生命周期与作用域严格绑定。int a = 10;、std::string s = "hello"; 这类定义在函数内部的变量,默认都在栈上分配。
关键点:
rsp 或 esp)stack overflow
int arr[n];(n 非 const)在标准 C++ 中是非法的(除非用 VLAs 扩展,但非标准且危险)int x; 不等于 0
new / delete 或 malloc / free
堆用于运行时不确定大小或需跨函数存活的数据,比如大数组、对象、容器内部缓冲区。典型写法:
int* p = new int[1000000]; // 分配 100 万个 int // ... 使用 p ... delete[] p; // 必须用 delete[],否则未定义行为
常见陷阱:
new 和 delete 必须配对;new[] 和 delete[] 必须配对 —— 混用会导致内存损坏或崩溃delete → 内存泄漏;重复 delete → 未定义行为(常见 crash)malloc 返回 void*,不调用构造函数;new 会调用构造函数,且可被重载除了栈和堆,C++ 程序实际还有几个固定区域:
立即学习“C++免费学习笔记(深入)”;
static 变量、全局变量(如 int g_val = 42;),程序启动时分配,结束时释放,零初始化const 全局变量(如 "hello world"),只读,试图修改会触发 segmentation fault
static int buf[1024];),加载时不占磁盘空间,运行时清零直接用 new/delete 容易出错,标准库提供了更安全的替代方案:
std::vector 替代 new int[n]:自动管理堆内存,异常安全,支持移动语义std::unique_ptr 管理单个堆对象:auto ptr = std::make_unique(arg1, arg2); // 构造即拥有 // 函数退出时自动 delete,无需手动干预
std::shared_ptr 管理共享所有权,但注意循环引用问题(可用 std::weak_ptr 打破)真正需要区分堆/栈的地方,往往出现在性能敏感路径(如避免 vector 频繁扩容)、嵌入式资源受限环境,或调试内存错误(valgrind 报告的 invalid read/write 位置能直接对应到分配方式)。