**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的区别和联系?
它们都是动态管理内存的⼊口;
malloc/free是C/C++标准库的函数,new/delete是C++操作符;
malloc/free只是动态分配内存空间/释放空间。⽽new/delete除了分配空间还会调⽤构造函数和析构函数进⾏初始化与清理(清理成员)。
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);
}