【C++】 内存空间布局、new/delete、malloc/free

本文介绍了C++中内存空间的布局,包括栈空间、堆空间、代码区和数据段。详细讲解了new/delete与malloc/free的区别,强调了内存管理的重要性,特别是防止内存泄漏,并提到了memset()在初始化内存中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存空间的布局

每个应用都有自己独立的内存空间,其内存空间一般都有以下几大区域

在这里插入图片描述

  • 栈空间

    每调用一个函数就会自动分配一段连续的栈空间来存储函数产生的局部变量,等函数调用完毕后会自动回收

    自动分配和回收

  • 堆空间

    需要主动去申请和释放

    • 在程序运行过程,为了能够自由控制内存的生命周期、大小、会经常使用堆空间的内存

      (需要用的时候就申请,不需要的时候手动释放

      • malloc \ free

        输入所需要的字节数,如果申请堆空间内存成功则返回第一个字节的地址。

        int *p = (int *) malloc(4);
        // 类型取决于将用这个地址做什么 
        *p = 10;
        // 用分配的4个字节来存放10
        free(p);
        

        使用完后将地址传入释放内存

        申请多少字节释放时就释放多少字节,不可以只释放部分字节。

        如果是char类型

        char *p = (char *) malloc(4);
        *p = 10; 
        // 10只放在所分配字节的第一个字节
        *(p + 1) = 20;
        // 给下一个字节
        // 等价于
        p[0] = 10;
        p[1] = 20;
        free(p);
        

        注意:指针变量p储存在栈空间

        在这里插入图片描述
        (X86环境 32bit 所以占4个字节,如果是64位环境则占8个字节

        栈空间的指针变量p指向堆空间的内容

        函数调用完毕消失的是栈空间的内容,堆空间内容不会消失,所以应该在函数调用完毕前释放所申请的空间。

      • new \ delete

        只要看到new就是向堆空间申请内存

        int *p = new int;
        // 申请四个字节
        
        *p = 10;
        delete p;
        char *p = new char; 
        // 申请一个字节
        
        *p = 10;
        delete p;
        // 释放一个字节
        // 如果要申请四个字节
        char *p = new char[4];
        delete[] p;
        // 如果new用了中括号,delete也得用中括号
        // 如果不加中括号的话,相当于只释放一个字节
        

        注意!new的不同用法!

        int *p0 = new int;
        // 没有初始化值;
        int *p1 = new int();	
        // 初始化为0;
        int *p2 = new int(5);	
        // 初始化为5;
        int *p3 = new int[3];	
        // 数组元素未被初始化;
        int *p4 = new int[3](); 
        // 3个数组元素都被初始化为0;
        int *p5 = new int[3]{}; 
        // 3个数组元素都被初始化为0;
        int *p6 = new int[3]{5};
        // 数组首元素被初始化为5,其他元素被初始化为0;
        
    • 申请堆空间成功后,会返回那一段内存空间的地址

    • 申请和释放必须是一对一的关系,不然会导致内存泄漏

      • new和malloc对比

        1. new内存分配失败时,会抛出bad_alloc异常,不会返回NULL;malloc分配内存失败时会返回NULL
        2. 使用new操作符申请内存分配时无需指定内存块的大小;malloc则需要显式地指出所需内存的尺寸
        3. operator new、operator delete可以被重载,但malloc和 free不能被重载
        4. new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构;而malloc不会
        5. malloc和free是C++/C语言的标准库函数;new/delete是C++的运算符
        6. new操作符从自由存储区上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。

        在这里插入图片描述

    memset()

    将较大的数据结构(比如对象、数组等)内存清零的比较快的方法。

    void * memset( void *_Dst, int _Val, size _t_Size )

    从 _Dst 开始,连续 _t_Size 个字节,每个字节的值都设为 _Val。

    int *p = (int *) malloc(sizeof(int) * 10);
    *p = 0; 
    // 只是将前四个字节初始化为0,并不能全部清零
    // 应该使用memset
    memset(p, 0, sizeof(int) * 10);
    // 对象清零
    Person person;
    person.m_id = 1;
    person.m_age = 10;
    person.m_height = 100;
    memset(&person,0,sizeof(person));
    Person persons[] = {{2,5,67}, {4,6,23}, {7,3,54}};
    memset(&person,0,sizeof(persons));
    
  • 代码区(代码段

    统一存放函数和所有代码

    是只读的不可以修改

  • 数据段(全局区

    用于存放全局变量等

    整个程序运行的时候都存在,不会自动释放

对象的内存可以存在于3种地方

  1. 全局区(数据段:全局变量
  2. 栈空间:函数里面的局部变量
  3. 堆空间:动态申请内存(malloc、new等)
// 全局区
Person g_person;
int main() {
    // 栈空间    
    Person person;
    // 堆空间    
    Person *p = new Person;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值