1
. 内存管理函数的层次
从下图中可以看到,C++
程序员处于的位置是最上层的Applications
,用的最多的是new
,new[]
,如果用容器,则内存基本不用管理。其次也可以调用malloc
。至于最底层的操作系统级别的API
,没有可移植性。它们之间的调用关系如上图的箭头所示。
2
. Memory primitives
分类
分配 | 释放 | 所属 | 可否重载 |
---|---|---|---|
malloc |
free |
C 函数 |
否 |
new |
delete |
C++ 表达式 |
否 |
::operator new() |
::operator delete() |
C++ 函数 |
可 |
allocator<T>::allocate() |
allocator<T>::deallocate() |
STL 分配器 |
可以自己设计搭配容器 |
1 | void primitives_sample() |
3
. new
的初步探究
c++
的程序员基本都会用new
来为对象分配一个堆内存,并且new
会调用对应的构造函数,构造函数是用来初始化对象的,所以总结出new
的功能是:
- 在堆中分配一块指定对象大小的内存
- 将返回的指针转换为指向对象类型的指针
- 通过指针调用对象相应的构造函数
4
. 测试new
的调用流程
1 | struct A |
上面的4
张图是在MSVC
中反汇编的运行时代码。从第1
张图可以看出,new
调用了operator new
,从第3
张图可以看出,operator new
内部调用了malloc
。实际上编译器是在new
的地方调用了对应的构造函数,并不是在new
的内部,new
只是编译器识别的一个标识符,并不是函数,编译器看到new
后会malloc
,然后调用构造函数。
VS2019
可以看到operator new
的源码:
1 | _CRT_SECURITYCRITICAL_ATTRIBUTE |
上面的operator new
的作用是调用malloc
分配内存。当malloc
成功后直接返回。当malloc
失败后,并不会再次malloc
,而是调用_callnewh() new_handler()
,这个函数的作用是向自己定义的函数索取内存,所以new_handler
可以理解为释放一些缓存,调用完new_handler
后,可能释放了内存,这个时候再尝试调用malloc
获取内存。
5
. delete
的初步探究
6
. 测试delete
的调用流程
1 | using namespace std; |