C++内存管理

内存管理基础

内存分区

C++中内存区分为四类:

  • 栈区:存储局部变量、调用信息、返回信息、临时变量等
  • 堆区:由malloc分配的内存块,需要free释放;C++中new/delete在逻辑上是分配内存到自由存储区。但自由存储区仅是逻辑结构,根据编译器和标准不同,有些new/delete本就借助malloc/free实现,所以其分配内存依旧坐落在堆区
  • 全局/静态存储区:存储全局变量静态变量。在C中还区分了初始化且非零变量和未初始化以及零变量,但在C++中未作区分。
  • 代码区:代码区包含二进制代码和常量,保持只读

如果要分为五类就是把代码区拆开。

堆和栈

最经典也最常用的示例:

void f(){char* cp = new char[5];}

在这行代码中,指针cp位于栈区,而通过new分配的内存,也就是指针cp指向的内存位于堆区
区别:

  1. 在内存中栈区位于顶层,堆区位于栈区下方,且两者中间隔着一块待分配内存。栈区内存由高位向低位增长,堆区内存由低位向高位增长。
  2. 栈区内存由编译器管理,而堆区内存由程序员创建和释放。
  3. 栈区内存大小更小,堆区内存更大。
  4. 栈区是先进后出队列,堆区会由于不断的申请、分配、释放内存造成大量碎片。
  5. 栈区有动态分配和静态分配,均由编译器管理;堆区只有动态分配。

分配

C++中更多是使用new/delete,而非malloc/free。虽然之前提到在不同标准和编译器中C++的new/delete也有可能就是malloc/free实现的,但是new/delete的重要性在于其对非内部数据类型的支持。
在有一定C++基础的情况下肯定能认识到OOP相对于POP(比如C++相对于C)具有的重要特性:封装、继承、多态。这些特性与非内部数据类型紧密相关。
在为这些数据类型分配内存时,由于部分成员变量被封装在内部,可能需要进行一些额外的操作(如初始化等),这就不可避免的依赖构造函数;而在释放这些内存之前也要进行一些资源的释放,这就依赖于析构函数。所以对于C++来说,new/delete的组合更加常用。

常见错误

  • 申请内存失败,但使用了
  • 申请内存成功,但未正确初始化
  • 申请内存成功,正确初始化,但越界访问——内存泄漏
  • 没有正确释放内存
  • 释放内存后使用

指针与数组

在使用中,指针和数组往往可以互换,但两者有核心区别:一个是变化的一个是静止的:指针其指向是可以改变的,可以代表不同的内存块;数组对应的内存块头地址是静止的,能改变的只有该段内存上的值。

char cp[] = "Hello";//在cp指向的内存上写入Hello
char *sp = "string";//将sp指向代码区(常量区)上的“string”字段

在这种情况下我们可以通过cp[0] = h来尝试修改“Hello”,但无法对“string"进行修改。

posted @ 2025-10-31 21:57  K0maru  阅读(18)  评论(0)    收藏  举报