🎇个人主页:Ice_Sugar_7
🎇所属专栏:C++启航
🎇欢迎点赞收藏加关注哦!
文章目录
- 🍉内存分布
- 🍉关键字new
- 🍉关键字delete
- 🍉new和delete的封装实现
- 🍉总结
- 🍉写在最后
🍉内存分布
C语言阶段我们知道程序内存主要分为五个区域:栈区、堆区、静态区、代码段和内存映射段
①栈区:存储
非静态局部变量、函数参数、返回值
等。栈是向下增长
的(从高地址
向低地址
增长)
②堆区:用于程序运行时动态内存分配
(比如malloc动态开辟空间)。堆可以向上增长(从低地址
向高地址
增长)
③静态区:存储全局数据和静态数据(比如static
修饰的变量)。静态区是语法层面的概念,后面学习操作系统的时候我们习惯称它为数据段
(操作系统层面的概念)
④代码段:存放可执行的代码
和只读常量
⑤内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存(Linux部分学习)
它们分布的示意图如下:
🍉关键字new
class A {
public:
private:
int _a;
};
int main() {
A* p = (A*)malloc(sizeof(A));
p->_a = 1;
return 0;
}
上述代码中p->_a = 1;
会报错,因为_a是私有成员
,也就是说malloc不方便处理动态申请的自定义类型对象的初始化问题
C++中的关键字new
则可以有效解决这个问题,来看一下如何使用new
//内置类型
int* p1 = new int;//动态申请1个整型大小的空间
int* p2 = new int[5];//动态申请5个整型大小的空间
int* p3 = new int(5);//动态申请1个整型大小的空间并初始化为5
//自定义类型(假设现在有一个类A)
class A {
public:
A(int x) { //构造函数
_a = x;
}
private:
int _a;
};
A aa1(1);
A aa2(1);
A aa3(1);
A* p4 = new A[3]{ aa1, aa2, aa3 };
A* p5 = new A[3]{A(2), A(2), A(2) };//匿名对象
A* p6 = new A[3]{ 3, 3, 3 };//构造+拷贝构造会被编译器优化为直接构造,即此处直接用3构造对象
通过对比,不难看出malloc只开辟空间
而new会做两件事:①开辟
一块空间;②进行初始化。比如对于自定义类型,就会调用
它的构造函数
(没有构造函数那就会报错)
由此可以看出,new和malloc主要的区别还是在自定义类型的动态内存的开辟上,内置类型除了用法不同,没有区别,只不过new比malloc更方便
此外,malloc申请内存失败会返回空指针,而new则会抛出异常,这更符合面向对象的思想
🍉关键字delete
有开辟就有释放,delete对应C语言的free,但是有所改进,delete除了释放空间,如果是自定义类型,那么还会调用析构函数
double* p1 = new double;
delete p1;
double* p2 = new double[10];
delete[] p2;
//假设有一自定义类型A
A* p3 = new A[2];
delete[] p3; //调用2次析构函数
注意:如果申请多个空间,一定要用delete[]
,不然结果是未定义的,有可能导致程序崩溃
🍉new和delete的封装实现
C++中new
和delete
都是操作符,它们在使用时分别会调用全局函数operator new
和operator delete
如果是new[ ]和delete[ ]则会分别调用operator new[]
和operator delete[]
,但是这两个函数最终也是调用operator new
和operator delete
●operator new
实际上是对malloc进行封装,不过有所改进。对于自定义类型的对象,会调用它的构造函数,失败时抛出异常等(其实就是上面所说的new相较于malloc的优势)
●operator delete
则是对free进行封装
●接着来说下new T[N]
,它实际是调用operator new函数完成N个对象空间的申请,也就是调用N次构造函数
●同理,delete[]
是调用N次析构函数,然后进行free
。中括号里面不用写数字的原因是new T[N]和delete[]是配合使用的,delete[]会自动根据N的大小来决定调用多少次析构函数
调用的途径如下:
new->operator new->malloc
delete->operator delete->free
new:先调用operator new申请空间,然后如果是自定义类型,则会调用构造函数
delete:先调用析构函数(自定义类型),然后再调用operator delete释放空间
🍉总结
最后总结一下malloc&free和new&delete的区别(面试题常考):
①malloc和free是
函数
,new和delete是操作符
②malloc申请的空间不会进行初始化,而new对于自定义类型会调用它的构造函数
③malloc申请空间时,需要我们手动计算所需空间的大小;而new只需写多少个所需类型大小的空间
④malloc返回值类型是void*
,接收返回值需要强制类型转换
;而new不用
⑤malloc申请空间失败的话,会返回空指针NULL,我们需要判断是否为空;而new不需要,但它需要捕获异常
⑥申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数;而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
🍉写在最后
以上就是本篇文章的全部内容,如果你觉得本文对你有所帮助的话,那不妨点个小小的赞哦!(比心)