c++动态内存管理

       **c语言动态内存管理**

c中关于动态内存的标准库函数:malloc() ,calloc() ,realloc(),free()

以下是关于这几个函数的介绍:

1、malloc(),用于动态开辟内存(堆空间),返回类型为void *,参数(size_t size)是无符号整型表示要开辟的空间大小,单位是字节,

2、calloc(),用于动态开辟内存(堆空间),返回类型为void *,参数有
(size_t num, size_t size ),表示开辟num个大小为size的空间,

3、realloc(),用于修改已经分配好的内存块的大小,返回类型为void ,参数(void memblock, size_t size),memblock是指向内存块的指针,size表示要开辟的空间大小;如果是扩大一个内存块,并且内存块能满足要开辟的大小,则内存块中原来的内容保持不变,新添加的内存添加在原来内存块的后面,若不能满足,则需重新开辟一块空间,并将原来的内容拷贝到新内存中,详见下图:
这里写图片描述
若是缩小一个内存块,该内存块尾部部分内存会被释放,剩余部分不变,如果memblock是空指针时,则和malloc()函数功能一样;

malloc()和calloc()都用于开辟内存,那它们有何区别?

malloc()开辟空间后,未将其内容进行初始化,内容为随机值;
calloc()开辟空间后,并将其内容初始化为0;

4、free(),用于释放内存空间,返回类型为void ,参数( void* memblock)memblock是指向内存的指针;

*注意:这四个函数必须搭配使用,即用malloc()、realloc()、calloc()时必须使用free(),这样可以避免内存泄漏甚至崩溃的问题。*

        **C++动态内存管理** 

c++动态内存管理的实现,是使用new,delect操作符来实现的:

例如:int *p1=new (int)//表示开辟一个整型的空间,在堆上开辟;
int *p2=new[10] (int)//表示开辟10个整型的空间;
delete p1;
delete[]p2;
注意:new与delect\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可⾃⼰计算类型的⼤⼩,返回对应类型的指针。

    由此可以看出c++中的new、delete更加的高效,更适用与c++,在实例化过程中更加适用;

new、delete的实现:

这里写图片描述
可以看到new的底层实现是通过 operator new()函数实现的;函数内部调用了malloc()函数开辟空间;即opertaor new()是对malloc的封装;

通过调试可以看出delete在实现时调用了operator delect(),它是对free()函数的封装;

总结:
1. operator new/operator delete operator new[]/operator delete[] 和 malloc/free⽤法⼀样。

2 它们只负责分配空间/释放空间,不会调⽤对象构造函数/析构函数来初始化/清理对象。

3.实际operator new和operator delete只是malloc和free的⼀层封装。

注意:operator new(),operator delete(),不是运算符的重载,它们是c++中的标准库函数。

new的功能有:
1. 调⽤operator new分配空间。
2. 调⽤构造函数初始化对象。

delete的功能:
1. 调⽤析构函数清理对象
2. 调⽤operator delete释放空间

new[N]的功能:
1. 调⽤operator new分配空间。
2. 调⽤N次构造函数分别初始化每个对象。

delete[]的功能:
1. 调⽤N次析构函数清理对象。
2. 调⽤operator delete释放空间。

通常用delete[]时没有给出次数,那编译器是如何知道,要调用析构函数的次数呢?

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<cstdlib>
using namespace std;

class A
{
  public:
    A(int a=1)
        :_a(a)
    {

    }

    ~A()
    {
    }
    void Display()
    {
        cout<<_a<<endl;
    }
private:
    int _a;
};
int main()
{ 
    A *p=new A[3];
    delete[] p;
    return 0;
}

调试后发现:
这里写图片描述
可以发现:operator(size_t cd),cd=16,即创建了16个字节的空间;
但开辟 3个A类对象只需12个字节,那为何会多出4 个字节呢?
经测试:
这里写图片描述
由此可知,多出来的4个字节是用来存放要开辟的对象个数的;
注意:只有当为非内置类型(类的对象等)开辟空间,并且该类有自定义的析构函数时,才会有多出的4个字节!

以上对new和delete的说明,可以模拟实现new的功能,在实现之前先介绍,定位new表达式;

定位new表达式:是在已分配的原始内存空间中调⽤构造函数初始化⼀个对象。

用法如下:
new (place_address) type
new (place_address) type(initializer-list)
place_address必须是⼀个指针,initializer-list是类型的初始化列表。

模拟实现new操作符,代码如下:

#define  NEW(p,count,type)\
{                      \
    p = (type *)malloc(count*sizeof(type)+4);\
    *(int *)p=count;        \
    p=(type *)(int *)p+1;   \
    for(int i=0;i<count;i++)\
    {                       \
        new(p+i) type(i);   \
    }                       \               
}

模拟实现delete:

DELECT(p)
{
    int count=*((int *)p-1);
    for(int i=0;i<count;i++)
    {
        p[i].~A();
    }
    free((int *)p-1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值