[C++]之内存管理(一)

一、C/C++内存分布

1.1.内存五大分区

1.栈:非静态局部变量、函数参数、返回值;向下增长。函数调用时临时开辟的一块内存,函数执行完这块内存就自动销毁;向下增长意思是:后开辟的变量,内存地址比先开辟的更小(地址往低地址方向走)

**2.堆:**动态内存申请,向上增长,自己手动申请的内存(new/malloc),不用了要手动释放;向上增长意思是:新申请的内存,地址比之前申请的更大(地址往高地址方向走)

**3.内存映射段:**共享库、共享内存、IO 。把磁盘上的文件、库文件直接映射到进程内存里,多个程序可以共用同一份库,不用全部拷贝到自己内存;用完由系统管理,不用自己手动申请释放。

**4.数据段(静态区):**全局变量、static静态变量。

👉通俗解释: 程序一运行就开辟、直到程序结束才销毁;所有对象共用这一块空间,变量存在这里,不会随着函数结束而消失。

**5.代码段(常量区):**可执行代码、只读字符串常量。

👉通俗解释:存放写好的程序指令和双引号里的字符串,只读不能修改;程序运行全程都在,多个进程可以共用这份代码。

1.2.实例变量内存位置辨析

1.全局/静态全局->数据段

2.局部普通变量:栈

3.static局部变量:数据段

4.字符串字面量:代码段

5.malloc申请内存:堆

复制代码
// 1.全局/静态全局 -> 数据段
int g_a = 10;                // 全局变量
static int sg_b = 20;       // 静态全局变量

int main()
{
    // 2.局部普通变量:栈
    int a = 100;            

    // 3.static局部变量:数据段
    static int s_c = 200;   

    // 4.字符串字面量:代码段
    const char* p = "hello"; 

    // 5.malloc申请内存:堆
    int* ptr = (int*)malloc(sizeof(int)); 

    return 0;
}

二、C语言动态内存管理

2.1.函数

1.malloc:申请size字节,不初始化,失败返回NULL

分配内存块

分配一块大小为 size 字节的内存,返回指向这块内存起始位置的指针。

举例:int* p = (int*)malloc(sizeof(int));

2.calloc:申请n个size字节,初始化为0,失败返回NULL

分配数组内存并初始化为 0

为包含 num 个元素的数组分配一块内存,每个元素占 size 字节,并且把内存里所有位全部初始化为 0。

举例:

// 申请5个int空间,每个int占4字节,全部自动初始化为0

int* arr = (int*)calloc(5, sizeof(int));

3.realloc:扩容/缩改已有内存块,返回新地址。

重新分配内存块

修改 ptr 指向的这块内存的大小。

参数说明:

ptr:之前 malloc/calloc/realloc 得到的堆内存指针;

size:调整之后新的总字节数

举例:int* tmp = (int*)realloc(p, 10 * sizeof(int));

4.free:释放堆内存,不能释放栈内存。

释放内存块

把 ptr 指向的堆内存还给操作系统。

参数:ptr 是之前 malloc /calloc/realloc 返回的堆指针

⚠️ free不会把指针本身清空,也不会把内存里的数据清零!

2.2.malloc、calloc、realloc三者的区别

malloc: 在堆区分配指定字节数的连续内存空间,不对内存内容做初始化。申请一块堆空间,里面保留原来的随机垃圾值。

calloc :在堆区分配指定数量、指定大小的连续内存空间,并将内存全部初始化为 0。申请一块堆空间,申请好直接全部置 0。

**realloc:**重新调整一块已分配堆内存的总字节大小,保留原有有效数据。给已经申请好的堆空间扩容或者缩容。

三、C++动态内存new/delete

3.1.内置类型

1.new 类型

申请空间,在堆区为单个内置类型对象分配内存,不主动初始化,返回该类型的指针。

复制代码
int* p = new int;

2.new 类型(值)

申请加初始化,在堆区分配单个该类型的内存空间,同时用括号内的值完成初始化,返回对应类型指针。

int* p = new int(20);

3.new 类型N

申请N个连续的空间,在堆区分配N 个该类型、连续的内存空间(数组空间),默认不初始化,返回首元素指针。

int* p = new int5;

4.delete释放单个,delete 释放数组,必须配对

delete 用于释放由 new 开辟的单个对象内存;delete\[\] 用于释放由 new\[\] 开辟的数组内存。new 和 delete、new \[\] 和 delete \[\] 必须严格配对使用,混用属于未定义行为,程序可能崩溃、内存泄漏。

复制代码
// 单个
int* p1 = new int(10);
delete p1;

// 数组
int* p2 = new int[5]{1,2,3};
delete[] p2;

3.2.自定义类型

1.new:开辟空间+调用构造函数

new 先在堆区分配内存空间,分配成功后,自动调用对应类型的构造函数完成对象初始化,最后返回对象指针。

2.delete:调用析构函数+释放空间

delete 先调用指针指向对象的析构函数,完成对象资源清理;再释放该对象在堆上的内存空间。

delete\[\] 会依次调用数组中每一个对象的析构函数,全部清理完毕后,再释放整块数组内存。

3.malloc/free:只开辟/释放空间,不调用构造/析构函数。

malloc 仅在堆区申请一块原始内存,不会调用类的构造函数;free 仅回收这块堆内存,不会调用析构函数,没有对象的初始化与资源清理逻辑。

相关推荐
codebolt1 小时前
C++程序crash分析和内存检测
开发语言·c++
椒颜皮皮虾྅1 小时前
让 C# 读懂整张图:DeploySharp 驱动 PaddleOCR v4/v5/v6,打通 OCR 全流程
开发语言·人工智能·深度学习·学习·c#·ocr·cuda
Java后端的Ai之路1 小时前
01、Java并发编程:学习攻略如何才能学好并发编程?
java·开发语言·学习
ShineWinsu1 小时前
对于Qt:QLabel常见属性的解析
c++·qt·面试·笔试·gui·标签·qlabel
corey932 小时前
Linux 学习 - 第十四周作业
linux·运维·学习
zwc32104320552 小时前
Day 5:threshold与inRange阈值分割
c++·图像处理·人工智能·opencv·算法·计算机视觉
小徐不徐说2 小时前
数据库存储基础:理解表结构、主键、事务与 BLOB
开发语言·数据库·c++·qt·程序设计
草莓熊Lotso2 小时前
【C++ 基于微服务的即时通讯系统】网关基建:cpp-httplib 与 WebSocketpp 从入门到实战
linux·开发语言·数据库·c++·redis·微服务·云原生
Sakura_j_h_11 小时前
EasyEDA PCB 快速设计Skills
c++·python·github