C中常用的动态内存开辟的函数有malloc,calloc,realloc。我们先来讲解这三个函数的用法。
1.malloc
头文件:#include<stdlib.h>
引用格式:void* malloc(size_t size)
含义: 向内存申请size个字节的空间,并返回该块空间的起始地址。如果开辟失败,将返回NULL
注意默认的返回类型是void*,实际使用时会在malloc前面加上想要强转成的类型
用法举例:
int* p = (int*)malloc(10 * sizeof(int));//可写成(int*)malloc(40);
//malloc申请完之后,必须要检验是否申请成功
//如果申请失败,将返回一个NULL
if (p == NULL)
{
printf("%s\n", strerror(errno));//将相应的错误码所对应的错误信息打印出来
}
else
{
//...
}
2.calloc
头文件:#include<stdlib.h>
引用格式:void* calloc(size_t num,size_t size)
num-元素个数
size-每个元素所占的字节数
含义: 向内存申请numsize个字节的空间,并返回该块空间的起始地址*,并将其中的元素值都初始化成0。如果开辟失败,将返回NULL。
用法举例:
int*p=(int*)calloc(10, sizeof(int));
if (p = NULL)
{
printf("%s\n", strerror(errno));
}
else
{
//...
}
3.realloc
头文件:#include<stdlib.h>
引用格式:void* realloc(void*memblock,size_t size)
memblock-要调整的空间的地址
size-调整之后的内存大小(不是新增的大小)
含义:实现扩容,并返回新空间的起始地址。扩容失败时,会返回NULL。
使用该函数有两种情况:
1.如果原申请空间的后面有足够空间可以追加,则直接在原空间后面追加,返回原先的地址
2.如果没有足够的空间可以追加,则realloc函数会重新找一块内存区域,开辟全新的一块满足需求的空间,然后拷贝原申请空间中的内容至新空间,释放原空间,并返回新空间的地址。
用法举例:
int main()
{
int *p=(int*)malloc(20 * sizeof(int));
if (p == NULL)
{
printf("%s\n", strerror(errno));
}
else
{
//...
}
//如果在这里发现20个字节不够用了,想开辟40个字节的空间,就可以用realloc函数调整空间大小
int* ptr=(int*)realloc(p, 40 * sizeof(int));
//注意!!!扩展空间后,不能直接赋给原来的地址。
//因为如果申请失败,返回的是null,此时若直接赋给原来的地址,会导致原先地址上的数据丢失
if (ptr == NULL)
{
printf("%s\n", strerror(errno));
}
else
{
//...
}
如果将realloc的第一个参数设置成NULL,还可以直接用来开辟空间,此时相当于malloc:
int* p = realloc(NULL, 40);//等价于malloc(40)
C中常用的动态内存释放的函数是free。对于malloc,realloc,calloc等通过动态内存开辟出来的空间,必须通过free释放
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
//当动态申请的空间不再使用时,需要返还空间
free(p);
return 0;
}
C++中用于动态内存开辟的函数是new.要注意new是操作符,但malloc\calloc\realloc都是函数。
(1)对于内置类型(,char,short,int,float,double,指针等),new与malloc作用上一致,就是写法上有所不同
int main()
{
//申请一组空间
//C
int* p1 = (int*)malloc(sizeof(int) * 10);
//C++
int* p2 = new int[10];
//申请单个对象
//C
int* p3 = (int*)malloc(sizeof(int));
//C++
int* p4 = new int;
//C
free(p1);
free(p3);
//C++
delete [] p2;
delete p4;
return 0;
}
另外,使用new对内置类型开辟空间时,还可以自带初始化 例如:
int* p1 = new int(1);//小括号用于单个数据的赋初值,中括号用于申请多个空间时申明空间大小
int* p2 = new int[4]{ 1,2,3,4 };//不用写等号
(2)如果针对自定义类型,比如类,malloc只有开辟空间,new包括开辟空间加上构造函数初始化`
class ListNode
{
private:
int _val;
ListNode* prev;
ListNode* next;
public:
ListNode()
{
prev = nullptr;
next = nullptr;
_val = 0;
}
};
int main()
{
ListNode* p1 = (ListNode*)malloc(sizeof(ListNode));
ListNode* p2 = new ListNode;
return 0;
}
可以看到,p1中的三个成员变量都是随机值,p
2中的都已经按照构造函数初始化完毕了。
C++中常用的动态内存释放的函数是delete。类似的,delete与free的区别是:
对于内置类型两者相同;
对于自定义类型,
free只有释放空间,delete针对自定义类型包括析构函数清理 + 释放空间