1.new/delete和malloc/free理解
class A {…};
A* Ptr = new A;
A* Ptr = (A*)malloc(sizeof(A));
new和malloc都是动态内存分配函数,delete/free负责对应new/malloc内存释放,不能混搭。其中,new/delete是C++中的操作符,malloc/free是C语言中的函数。
区别
分配内存:
- new会调用构造函数,编译器按数据类型自动分配内存。delete会调用析构函数
- malloc必须指明申请内存空间的大小。free释放malloc分配指针指向的空间
返回类型:
- new分配内存成功后返回指定类型的对象指针,类型安全;分配失败后抛出std:bad_alloc异常(A* Ptr = new
(std::nothrow) A;new失败就不会抛出异常而是会返回空指针)。 - malloc分配内存成功后返回void*,然后再进行强制类型转换;失败返回null。
下面了解就行:
使用new操作符来分配对象内存会有三个步骤:首先调用operator new函数,分配一个足够大的未命名空间来存储特定类型的对象。然后,编译器运行构造函数,并为其传入初始值。最后构造完成,返回一个指向该对象的指针。
使用delete释放对象会有两个步骤:首先调用对象的析构函数,其次编译器调用operator delete释放内存空间。
因此使用new和delete能够调用构造和析构函数并且初始化对象,而malloc和free不能。
对数组的处理:可以使用new和delete[]创建和释放数组对象。而malloc无法判断开辟的空间是存放数组还是单个对象,需要我们自定义数组的整个内存大小。
分配内存的位置:
malloc是从堆上动态分配内存
new是从自由存储区为对象动态分配内存。自由存储区的位置取决于operator new的实现。自由存储区不仅可以为堆,还可以是静态存储区,这都看operator new在哪里为对象分配内存。很多编译器的new/delete都是以malloc/free为基础来实现的,所以通常都是借由堆实现来实现自由存储,这时候也可以说new所申请的内存区域在堆上。
是否可以被重载:
opeartor new /operator delete可以被重载。
而malloc/free则不能重载。
能否重新扩充内存:
当发现当前内存不够时,可以使用remalloc进行内存扩充
两种情况,一是当前指针所指向内存有足够大的内存空间时,原地扩大可分配的内存地址,并返回原内存地址指针。
当连续内容不够时,按新内存大小开辟一个新内存,并将原始数据复制到新内存中,然后释放原来的存储区域,并且返回新内存的地址指针。
new没有这种机制。
2.野指针
野指针是指程序员或操作者不能控制的指针。野指针不是NULL指针,而是指向“垃圾”的指针。
“野指针”出现有两种情况:
1.指针变量没有初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。
解决方法:在初始化时赋值。
2.指向已删除对象的指针变量。指针变量被free或delete之后,没有设置为NULL。它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。
解决方法:指向删除对象的指针设为null
free (ptr);
ptr=null;
理解:
free函数只是将参数指针指向的内存归还给操作系统,并不会把参数指针置NULL,为了以后访问到被操作系统重新分配后的错误数据,所以在调用free之后,通常需要手动将指针置NULL。
从另一个角度来看,内存这种底层资源都是由操作系统来管理的,而不是编译器,编译器只是向操作系统提出申请。所以free函数是没有能力去真正的free内存的。只是告诉操作系统它归还了内存,然后操作系统就可以修改内存分配表,以供下次分配。
free(ptr)后ptr指针仍然指向原来的堆地址,即你仍然可以继续使用,但很危险,因为操作系统已经认为这块内存可以使用,他会毫不考虑的将他分配给其他程序,于是你下次使用的时候可能就已经被别的程序改掉了,这种情况就叫“野指针”。
部分内容转自:https://blog.csdn.net/qq_41282070/article/details/108636790