目录
3.operator new与operator delete函数
1.C语言中动态内存管理方式
malloc:动态开辟sizeof个字节的空间
calloc:动态开辟sizeof个字节的空间,并按字节初始化
realloc:增加或者减少动态开辟的空间;分为原地开和异地开2种,如果有数组后足够的原地开直接在数组后增加,否则在内存内找一块合适的空间,把原数组的拷贝给新数组,在free掉旧数组,把原指针指向新数组;
realloc:可以当malloc一样直接使用;
void Test()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof(int));
cout << p2 << endl;
int* p3 = (int*)realloc(p2, sizeof(int) * 1000000);
cout << p3 << endl;
// 这里需要free(p2)吗?
//不需要p3是原地开,p3就是p2,异地开会free(p2)
free(p3);
}
int main()
{
Test();
return 0;
}
2.C++内存管理方式
1 new/delete操作内置类型
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力而且使用起来比较麻烦(构造对象),因此C++又提出 了自己的内存管理方式:通过new和delete操作符进行动态内存管理
int main()
{
//new和delete和malloc和free在针对内置类型上没有差别,只是用法不同
//申请10int类型的数组
int* p1 = (int*)malloc(sizeof(int) * 10);
int* p2 = new int[10];//不需要强转,new是操作符
free(p1);
delete[] p2;
//申请单个int对象
int* p3 = (int*)malloc(sizeof(int));
int* p4 = new int;
free(p3);
delete p4;
return 0;
}
2 new和delete操作自定义类型
注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会
struct ListNode
{
public:
ListNode(int val=0)
:next(nullptr)
,prev(nullptr)
,val(val)
{}
~ListNode()
{
cout << "~ListNode()" << endl;
}
private:
ListNode* next;
ListNode* prev;
int val;
};
int main()
{
//c malloc只是开空间,free释放空间
struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));
free(n1);
//cpp new针对自定义类型,开空间+构造函数初始化
// delete针对自定义类型,析构函数+释放空间
ListNode* n2 = new ListNode;
delete n2;
ListNode* n3 = new ListNode[4]{1,2,3,4};
delete[] n3;
//delete n3;//不匹配会崩溃
return 0;
}
3.operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的 全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
struct ListNode
{
public:
ListNode(int val=0)
:_next(nullptr)
,_prev(nullptr)
,_val(val)
{}
private:
ListNode* _next;
ListNode* _prev;
int _val=5;
};
int main()
{
//operator new该函数实际通过malloc申请空间,当malloc申请成功时直接返回,申请失败,尝试执行空间不足应对措施,
//如果用户改应对措施了,则继续申请,否则抛异常
struct ListNode* p1 = (struct ListNode*)malloc(sizeof(struct ListNode));
free(p1);
struct ListNode* p2 = (struct ListNode*)operator new(sizeof(struct ListNode));
operator delete(p2);
return 0;
}
operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的
4. new和delete的实现原理
new的原理
1. 调用operator new函数申请空间,operator new就是malloc的封装,开辟失败抛异常,抛异常不会结束程序
2. 在申请的空间上执行构造函数,完成对象的构造
delete的原理
1. 在空间上执行析构函数,完成对象中资源的清理工作(先调用)
2. 调用operator delete函数释放对象的空间
delete[N]的原理
1. 在释放的对象空间上执行N次析构函数,再析构整体
5. 常见面试题
1 malloc/free和new/delete的区别
malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。 不同的地方是:
- malloc和free是函数,new和delete是操作符
- malloc申请的空间不会初始化,new可以初始化
- malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
- malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
- malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
- 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
2 什么是内存泄漏,内存泄漏的危害
- 什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而 造成了内存的浪费。
- 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
3 如何一次在堆上申请4G的内存?
切换64位的进程
#include <iostream>
using namespace std;
int main()
{
void* p = new char[0xfffffffful];
cout << "new:" << p << endl;
return 0;
}