动态内存管理:
动态内存是程序员对系统内存的维护操作。我们知道系统中常见的几个空间有栈、堆、静态区和常量区。通常情况下,在程序中定义的对象都有对应的生命周期,其中在main函数或者其他调用的函数中直接定义的对象编译器会将其保存在栈区,保存在栈区的对象出了生命周期便会被系统自动销毁回收,而由程序员通过内存管理的对象会在堆区被创建,其生命周期在在程序员创建到主动调用销毁或者程序结束系统强制销毁之间。而内存的动态管理方式是程序必不可少的一部分,在c/c++程序中广泛使用。
c语言的动态内存管理
c语言的动态内存管理比较繁琐,其执行方式为调用函数malloc/calloc/realloc,参数内容为开辟的空间大小然后返回void*指针,由程序员强行转换至所需求的类型。
int main()
{
// 调用malloc函数可以直接开辟指定的空间,但是其内容不会进行初始化
int* a = (int*)malloc(sizeof(int));
// 调用calloc具有malloc的功能,而且会自动将内容置为0
int* b = (int*)calloc(b * sizeof(int));
// realloc -- 将修改指针指向的空间为指定的空间大小
-- 当指针为NULL时,realloc作用和malloc相同
int* c = NULL;
c = (int*)realloc(c , sizeof(int));
// 空间开辟后需要手动销毁,如果没有指令销毁,被分配的空间会一直占用系统资源直至程序结束
free(a);
free(b);
free(c);
return 0;
}
空间使用结束后,必须通过free()释放空间,但是没有释放不会引起编译报错。
free()的使用很简单,在参数填写指向空间的指针,程序就会执行释放的动作。
c++的动态内存管理
相比于c语言,c++的动态内存比较暴力,通过new和delete运算符可以完成空间开辟和释放。
int main()
{
// 直接在new后面加上类型就可以完成内存分配
int* p1 = new int(1); // *p1 = 10
// 数组开辟在类型后加[n],便可完成指定的内存分配
int* p2 = new int[10]{1}; // *p2 = { 1 , 0 , 0 ...}
// 释放空间使用delete 和 delete[]
delete p1;
delete[10] p2;
return 0;
}
值得一提的是,new不会自动对c++内置的单个类型(int、double)进行初始化,但是它提供初始化的功能,而且在对数组进行分配时,如果没有指定初始化内容则默认为0。尤其注意的时:在内存分配使用结束时,delete对应的new,delete[]对应的new[],不匹配使用可能会出现各种奇葩情况。😊
相较于malloc,new看起来没有太突出的优点,因为实质上new是针对malloc无法手动初始化对象而设计的,在对象的定义时,malloc / calloc最多只会初始化,而new不仅仅有初始化内置类型的功能,对于自定义类型,基于c++中对象拥有构造函数和析构函数,new使用会自动调用构造和析构从而达到初始化的效果。
class ListNode
{
public:
ListNode(int val)
:_val(val)
,_next(nullptr)
{}
~ListNode()
{
_val = 0;
_next = nullptr;
}
int _val;
ListNode* next;
};
int main()
{
listNode* a1 = new ListNode(1);
listNode* a2 = new ListNode(2);
listNode* a3 = new ListNode(3);
listNode* a4 = new ListNode(4);
listNode* a5 = new ListNode(5);
a1->next = a2;
a2->next = a3;
a3->next = a4;
a4->next = a5;
delete a1;
delete a2;
delete a3;
...
return 0;
}
总结:malloc和new都是从堆上申请空间,并且都需要手动释放。不同的是
1.malloc和free是函数,而new和delete是操作符
2.malloc不能对对象初始化,而new可以
3.malloc申请空间需要指定空间大小,而new不需要,若需要开辟数组只需在类型后面加上[n]即可
4.malloc返回值是void*,使用时需要强制转换,new则不用
5.malloc开辟空间异常时返回NULL,而new开辟空间失败则抛异常(下章讲解)
6.malloc只会开辟空间,而new会开辟空间而且调用构造函数;free释放空间,delete不仅释放空间还调用析构函数。
本章简单记录一下new的使用,下章更新new和delete的底层原理。