一、C的动态内存开辟
- malloc函数:void* malloc(size_t size);向内存申请一块连续可用的内存空间,并返回这块空间的指针;
- calloc函数:void* calloc(size_t num,size_t size);开辟num个大小为size的空间,并且空间会被初始化为0;
- realloc函数:void*realloc(void* ptr,size_t size);如果要调整的区域ptr没有足够的空间扩容时,就会返回一个新的指针。
二、Cpp的动态内存开辟
2.1 内置类型
如上图,new一个int类型指针p1和一个int类型数组指针p2,并且将数组大小设置为5,通过对指针p1以及数组指针p2解引用进行赋值。
对于p3直接将其初始化为88;
在使用delete对开辟的变量进行资源释放,注意类型的匹配:数组释放delete[] p2。
2.2 自定义类型
如上图,对于自定义类型来说,如果使用new来创建该类型对象,此时就会自动调用该类对象的构造函数,当使用delete删除该类对象时,会自动调用该类对象的析构函数。
2.3 operator new与operator delete
那么new与operator new的区别是什么?
如上图,在进行断点调式后打开反汇编代码可以发现new操作其实是先调用operator new开辟空间,再调用构造函数进行初始化。
如上图,operator new与operator delete的结果其实并无区别,但区别在于operator new开辟空间是被会抛出异常,并且支持重载。
2.4定位new表达式
定位new表达式是在已分配的原始内存空间中调用构造函数初始化对象;
- new (place_address) type;
- new (place_address) type(initializer-list);
- place_address是一个指针,initializer-list是初始化列表;
如上图,A的数组大小为10,如何修改大小为20呢???
如上图,通过定位new来使数组大小更改为20。
三、总结
malloc\free与new\delete区别:
- 前者是函数,后者是操作符;
- 前者申请空间不会初始化,后者会初始化(调用了构造函数);
- 前者申请空间要传大小,后者不需要且[]可指定对象个数;
- 前者返回值类型为void*,需要强转,后者不需要;
- 前者开辟空间是被返回NULL,后者抛出异常并需要捕获;
- 对于自定义类型,前者只能开辟空间,后者可以开辟空间并初始化且会自动完成资源清理(调用了析构函数)。