Hello!!大家早上中午晚上好!!!今天继续复习内存管理部分知识点!!!
一、new/delete和malloc/free的区别
1.1对于申请单个空间内置类型没啥区别
int main()
{
int* p1 = (int*)malloc(sizeof(int));
int* p2 = new int;
int* p3 = new int(1);
free(p1);
delete p2;
delete p3;
return 0;
}
1.2对于申请多个空间内置类型没啥区别
int main()
{
int* p1 = (int*)malloc(sizeof(int) * 5);
int* p2 = new int[5];
int* p3 = new int[5] {1, 2, 3, 4, 5};
free(p1);
delete[]p2;
delete[]p3;
return 0;
}
对于内置类型要真说有点区别就是,new的时候无论单个空间还是多个空间都可以任意初始化,而malloc不行
1.3对于申请单个空间的自定义类型
class A
{
public:
A()
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A;
free(p1);
delete p2;
return 0;
}
运行:
对于申请单个空间,new自定义类型会在new的时候调用构造函数创建对象,在delete的时候调用析构函数清理对象资源;malloc和free跟申请释放内置类型没区别;
1.4对于申请多个空间的自定义类型
int main()
{
A* p1 = (A*)malloc(sizeof(A) * 10);
A* p2 = new A[10];
free(p1);
delete[]p2;
return 0;
}
mallco跟malloc内置类型区别:
new多少个A就调用多少次A的构造:
free跟free内置类型没区别:
delete时,创建了几个对象就调用几次析构:
1.5小结
①malloc/free的使用对于内置类型和自定义类型都一样;
②new/delete的使用对于内置类型跟malloc/free没区别,对于自定义类型new n个对象就调用n次构造,delete时创建n对象就调用n次析构;
③new的时候可以初始化任意值,而malloc不能初始化(就算是calloc也只能初始化为0);
④注意new和delete申请释放单个空间、new[]和delete[]申请释放连续空间,配套使用!!!
二、operator new和operator delete
new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new的底层调用operator new全局函数来申请空间,delete的底层调用operator delete全局函数来释放空间;
2.1operator new
operator new当申请空间成功时,直接返回这块空间的地址;
operator new当申请空间失败时会先执行应对空间不足的措施,如果用户设置了该措施,则继续申请,否则抛异常;
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// report no memory
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
2.2operator delete
operator delete该函数最终是通过free来释放空间;
三、new和delete实现原理
3.1对于内置类型
new/delete和malloc/free基本类似;
3.2对于自定义类型
假设自定义类型为一个简单的Stack:
struct Stack
{
public:
Stack()
{
_array = (int*)malloc(sizeof(int) * 20);
if (_array == NULL)
{
perror("Stack()");
}
_capacity=20;
_size=0;
}
~Stack()
{
if(_array)
free(_array);
_array = NULL;
}
private:
int* _array;
int _capacity;
int _size;
};
new实现原理:
①先调用operator new开空间;
②再在开好的空间上调用构造函数创建对象;
new[]实现原理:
①先调用operator new[]函数,operator new[]实际上是调用operator new函数申请n个对象空间;
②再在开好的n个对象的空间上调用n次构造函数对n个对象进行初始化工作;
delete实现原理:
①在空间上执行析构函数,完成对象资源的清理工作;
②调用operator delete函数释放对象空间;
delete[]实现原理:
①在n个对象空间上执行n次析构函数,完成对n个对象资源的清理工作;
②调用operator delete[]函数,operator delete[]函数实际上是调用operator delete释放n个对象空间;
四、总结new/malloc 和delete/free 区别
唯一共同点是new和malloc都时在堆上申请开辟空间,且都需要手动释放;
不同点:
1.malloc和free是函数,new和delete是操作符;
2.malloc需要手动传入开辟空间字节数大小,new只需要在后面跟上对象类型就行,如果new多个对象只需要new []里面添加个数即可;
3.malloc如果申请失败返回空值,所以使用前必须判空,new不需要但new需要捕获异常;
4.malloc出来后的空间地址需要强转,new不需要,因为new后面跟的是对象类型;
5.malloc空间不会初始化,new可以初始化;
6.malloc、free空间不会调用构造、析构函数;new会先开空间再调用构造函数,delete会先调用析构函数再释放空间;
五、内存泄漏
5.1什么是内存泄漏?
内存泄漏指的是因程序的错误设计,造成程序未能释放已经不使用的内存。内存泄漏并不是指内存在物理上的消失,而是因错误设计导致丧失对某内存段的控制,从而造成内存浪费!
5.2内存泄漏的危害?
长期运行的程序造成内存泄漏后果很严重,例如操作系统、后台服务等,出现内存泄漏会导致响应越来越慢,最终卡死
六、如何避免内存泄漏?
1、良好的程序设计规范,良好的代码编写规范,只要有动态内存申请的地方就记得配套内存释放;
2、有时候碰上异常,记得释放了也无济于事,这时就得使用智能指针解决;
3、使用内存泄漏检测工具;
几款内存检测工具:
4、简而言之,事前预防使用智能指针,事后补救使用内存泄漏检测工具!
今天就复习到这里!如果您觉得有收获请点赞收藏+关注!谢谢!!
如果您有更好的意见欢迎评论区留言!!
咱们下期见!!!