C++动态内存管理

来源:互联网 发布:西安软件新城附近楼盘 编辑:程序博客网 时间:2024/06/14 17:57

要研究C++动态内存管理,
我们的先了解一下C语言中的malloc/calloc/realloc/free.

void* malloc(size_t Size);

malloc在动态存储区分配一块空间为size字节大小的连续区域;没有对其初始化

void* calloc(size_t count,size_t size);

calloc在动态存储区里边分配一块长度为count,size字节大小的空间。并把这块内存初始化为0;

void* realloc(void* Memory,size_t Newsize);

realloc用于修改一个原先已经分配好的内存空间,如果要开辟的空间大于原来的空间,就在原来的空间
后边看还有没有足够的空间,如果有就直接在后边在开辟一点空间。如果不够就重新找一块连续的区域。
增加的空间不进行初始化。
如果Memory等于NULL,那么它和malloc作用相同。

例子:

int main(){    int *p1 = (int*)malloc(sizeof(int)); //开辟一个字节的空间    int* p2 = (int*)calloc(3, sizeof(int));//开辟3个字节的空间    int *p3 = (int*)realloc(p2, 5 * sizeof(int)); //在p2的基础上扩容开辟5个字节的空间    free(p1);    free(p3);    return 0;}

C++动态内存管理

C++通过new/delete来管理内存
new/delete管理对象
new []/delete[] 管理对象数组。

例子:

int main(){    int *p1 = new int; //开辟一个字节大小的空间    int* p2 = new int(6);//开辟一个字节大小的空间并初始化为6    int* p3 = new int[6];//开辟6个字节大小的空间    delete p1;    delete p2;    delete[]p3;    return 0;}

【malloc/free和new/delete的区别与联系】
1. 它们都是动态管理内存的入口
2. malloc/free是C/C++的库函数,new/delete是C++的操作符。
3. malloc/free只是动态的开辟空间释放空间,而new/delete除了会分配空间还会调用构造函数
和析构函数进行初始化和清理工作。
4. malloc/free需要手动的计算size还有返回时void*,new/delete会自动计算空间的大小,
返回对应类型的指针

class AA{public:    AA()        :_a(NULL)    {        cout << "AA()" << endl;        _a = new int(0);    }    ~AA()    {        cout << "~AA()" << endl;        if (_a)        {            delete _a;            _a = NULL;        }    }private:    int *_a;};void TestAA(){    AA* tmp = new AA[10];    cout << "多开辟了那四个字节存放什么?" << *((int*)tmp - 1) << endl;    delete[]tmp;}

在这里猜一下会开辟多大的空间?

这里写图片描述

为什么会多开辟4个字节大小的空间。
我们猜想可能是存放的析构次数。
然后我们用这个表达式*((int*)tmp - 1)打印出那块空间
这里写图片描述

在这里new[N]做了两件事:
1. 调用operator new[] 开辟空间
2. 调用了N次构造函数进行初始化。

delete[]也做了两件事:
1. 调用了N次析构函数进行清理工作
2. 调用了operator delete []释放空间。

定位new表达式
作用:是在已分配的原始空间上调用构造函数进行初始化一个对象。
new (place_address)type
new (place_address)type(initializer-list)
place_address必须是指针。 type类型

我们也可以用malloc和free模拟实现new/delete

void TestAA(){    AA* tmp = new AA[10];    cout << "多开辟了那四个字节存放什么?" << *((int*)tmp - 1) << endl;    delete[]tmp;    AA* tmp = (AA*)malloc(10 * sizeof(AA));//模拟上边    for (size_t i = 0; i < 10; i++)    {        new (tmp + i)AA;    }    for (size_t i = 0; i < 10; i++)    {        tmp[i].~AA();    }    free(tmp);}

我们还可以模拟它的那四个字节存放析构次数的功能

class AA{public:    AA()        :_a(NULL)    {        cout << "AA()" << endl;        _a = new int(0);    }    ~AA()    {        cout << "~AA()" << endl;        if (_a)        {            delete _a;            _a = NULL;        }    }private:    int *_a;};AA* New(size_t N){    AA* tmp = (AA*)malloc(N*sizeof(AA)+sizeof(int));//多开辟4的字节的空间    *((int*)tmp) = N; //在那四个字节里存放析构次数    tmp = (AA*)((int*)tmp + 1);//把空间向后置四个字节大的大小    for (size_t i = 0; i < N; i++)    {        new (tmp + i)AA;//调用new的定位表达式初始化    }    return tmp;}void Del(AA* pt){    int N = *((int*)pt - 1); //算出空间的前4个字节    AA* p = (AA*)((int*)pt - 1); //记录malloc起初的位置    for (size_t i = 0; i < N; ++i)    {        pt[i].~AA(); //调用析构函数清理工作    }    free(p);}void TestAA(){    AA* tmp = New(10);    cout << "多开辟了那四个字节存放什么?" << *((int*)tmp - 1) << endl;    Del(tmp);}

深度剖析new/delete & new[] /delete []

这里写图片描述

原创粉丝点击