【C++】深入解析C/C++内存管理:new与delete的使用及原理(一)https://developer.aliyun.com/article/1617320
第一点:
int* p0 = (int*)malloc(sizeof(int)); int* p1 = new int;
第二点:
int* p2 = new int[10]; int* p3 = new int(10); int* p4 = new int[10]{ 1,2,3 };
第三点:
struct ListNode { ListNode* _next; int _val; ListNode(int val) :_val(val) ,_next(nullptr) {} }; //创建不带哨兵位,同时如果是插入数据,new ListNode(3)即可 ListNode* CreateList(int n) { ListNode head(-1); ListNode* tail = &head; int val; printf("请依次输入%d个节点的值:>", n); for (size_t i = 0; i < n; i++) { cin >> val; tail->_next = new ListNode(val); tail = tail->_next; } return head._next; }
第四点:
void func() { int n = 1; while (1) { int* p = new int[1024 * 1024*100]; cout <<n<<"->"<< p << endl; ++n; } } int main() { try { func(); } catch (const exception& e) { cout << e.what() << endl; } return 0; }
这里try和catch就是捕捉异常,这一点到后面有涉及。以上种种都是new的优点,所以我们不推荐再使用malloc/free
系列。
四、 new和delete原理及其两个全局函数的实现(operator new/operator delerte)
new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new再底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间(operator new与operator delete不是对new和delete的重载)
int* p1 = (int*)operator new(10 * 4); //int* p1=new int(10*4) operator delete(p1); //delete(p1)
从代码中可以看出来,new/delete和operator new/operator delete效果上是相同的。那么直接使用new/delete就行,operator new/operator delete对于我们来说是没用的,但是有这个东西说明在系统中有它们的一席之地的。
/* operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间 失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。 */ void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes void *p; while ((p = malloc(size)) == 0) //通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果 //malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施 //就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。 if (_callnewh(size) == 0) { // report no memory // 如果申请内存失败了,这里会抛出bad_alloc 类型异常 static const std::bad_alloc nomem; _RAISE(nomem); } return (p); } /* operator delete: 该函数最终是通过free来释放空间的 */ void operator delete(void *pUserData) { _CrtMemBlockHeader * pHead; RTCCALLBACK(_RTC_Free_hook, (pUserData, 0)); if (pUserData == NULL) return; _mlock(_HEAP_LOCK); /* block other threads */ __TRY /* get a pointer to memory block header */ pHead = pHdr(pUserData); /* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); _free_dbg( pUserData, pHead->nBlockUse ); __FINALLY _munlock(_HEAP_LOCK); /* release other threads */ __END_TRY_FINALLY return; } /* free的实现 */ #define free(p) _free_dbg(p, _NORMAL_BLOCK)
可以通过上述两个全局函数的实现,可以知道,operator new实际是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施;如果用户提供该措施就继续申请,否则就抛异常。operator delete最终是通过free来释放空间的。
内置类型:
如果申请的是内置类型的空间,new/malloc与delete/free基本类似,不同的地方是new在申请空间失败时会抛异常,malloc会返回NULL
自定义类型:
new的原理:
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
delete的原理:
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete含函数释放对象的空间
new T[N]的原理:
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
- 在申请的空间上执行N次构造函数
delete[]的原理:
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间
通过汇编,深入立即其中
对于自定义类型转换指令只有两个核心动作调用全局函数及其构造或析构,而内置类型只有调用全局函数。
对此可得:
- operator new是对malloc的封装,如果失败抛异常,实现new
- operator newp[]封装operator new,最终还是malloc
- operator delete对free的封装
- operator delete[]封装operator delete
同时这里需要注意调用顺序上的问题
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)https://developer.aliyun.com/article/1617323