C/C++动态内存管理

C语言动态内存管理

C语言使用malloc、calloc、realloc来进行动态内存的管理。
malloc仅仅开辟一块空间,calloc开辟空间的同时并把它初始化为0,而realloc可以进行动态内存的调整。前面博客中已经介绍了这三个函数,在此不再赘述。
浅谈malloc、calloc和realloc

//C动态内存管理
void Test()
{
    int *p1  = (int*)malloc(sizeof(int)*4);
    free(p1);
    int *p2 = (int*)calloc(4,sizeof(int));
    int *p3 = (int*)realloc(p2,sizeof(int)*4);

    free(p2);
    free(p3);
}

需要注意的是,动态开辟的内存一定要手动释放,不然会造成内存泄露的危害。
下面我们主要说C++的动态内存管理。

C++动态内存管理

C++通过new和delete来动态管理内存。
new/delete动态管理对象,new[]/delete[]动态管理对象数组。
这里写图片描述
就像malloc和free要一起配合使用一样,new/delete,new[]/delete[]也要匹配使用。如果new出来的对象用free去释放,那么该对象因无法执行析构函数导致程序出错,相同的,用delete去释放malloc开辟出来的动态内存也有可能导致程序出错。所以,一定要匹配使用。

void Test1()
{
   int *p1 = new int;//动态开辟一块四字节空间,单个数据(1个int)
   int *p2 = new int(3);//动态开辟一块四字节空间并把它初始化为
   int *p3 = new int[3];//动态开辟3个四字节空间(12字节)

   delete p1;
   delete p2;
   delete[] p3;
}

我们知道C++是兼容C的,那么已经有C库的malloc和free了,为什么C++还要定义new和delete来动态管理内存?

malloc和new都可用来动态的开辟内存,而free和delete是用来释放空间。

C++中不仅有内置类型,而且还有自定义类型。对于内置类型,编译器本来就认识,不需要用户去定义,但是对于非内部类型,光用malloc和free不能满足动态对象的要求。对象在创建的时候要自动的去调用构造函数完成初始化,在释放的时候要自动的调用析构函数完成清理工作。由于malloc和free是库函数而不是运算符,不在编译器控制权限之内,所以不能把初始化和清理工作强加给malloc/free。因此C++需要提供一个能够完成动态内存分配和初始化工作的运算符new,以及一个能够完成清理和释放内存工作的运算符delete。

那么malloc/free和new/delete有什么区别和联系呢?
1)它们都是动态管理内存的入口。
2)malloc/free是C/C++标准库的函数,new/delete是C++操作符。
3)malloc/free只是动态分配内存空间/释放空间,而new/delete除了分配空间还会调用构造函数和析构函数进行初始化和清理(清理成员)
4)malloc/free需要手动的计算类型大小且返回值为void*,new/delete可自己计算,返回对应类型的指针。
5)malloc/free失败返回0,new/delete失败抛异常。

看下面这个例子:

class Array
{
public:
   //构造函数
    Array(size_t size = 10)
        :_size(size)
        , _a(0)
    {
        cout << "Array(size_t size)" << endl;
        if (_size > 0)
        {
            _a = new int[size];
        }
    }
    //析构函数
    ~Array()
    {
        cout << "~Array()" << endl;
        if (_a)
        {
            delete[] _a;
            _a = 0;
            _size = 0;
        }
    }
private:
    size_t _size;
    int *_a;
};

void Test()
{
    Array* p1 = (Array*)malloc(sizeof(Array));
    Array* p2 = new Array;
    Array* p3 = new Array(3);
    Array* p4 = new Array[3];

    free(p1);
    delete p2;
    delete p3;
    delete[] p4;
}

上面用了三次new,创建了5个对象,所以调用了5次构造函数和5次析构函数。
结果如下:
这里写图片描述

C++动态内存管理的过程如下:
1.开空间,调用operator new,底层是用malloc实现的;
2.调用构造函数完成初始化;
3.调用析构函数完成清理工作;
4.释放空间。

在这期间,new做了两件事:
1.调用operator new开空间
2.调用构造函数初始化对象
delete也做了两件事:
1.调用析构函数清理对象
2.调用operator delete释放空间

注意:开空间的时候没有直接调用malloc,而是先调用了operator new,原因是operator new失败了直接抛异常。
自定义类型调用new[]时,会多开四个字节,用来存对象的个数,是为了告诉delete要调多少次析构函数,而内置类型不会。

过程图如下:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值