核心简记
非动态的内存管理:由位置决定生存期,编译器自动释放
动态内存管理:自定义生存期,手动释放。
c++的动态内存管理运算符:
new,在堆中分配对象空间并返回指针,可以选择进行初始化。
delete,接受动态对象的指针,销毁对象,释放内存。
在memory头文件,标准库提供了俩种智能指针帮助管理动态对象,它依据指针生存期自动释放其指向的对象。shared_ptr共享对象,unique_ptr独占对象。
杂记:
- 编译器除了没有构造时生成默认构造外,还会在没有拷贝构造函数时自动生成拷贝构造函数。此外还有赋值、析构。其行为为对每个成员拷贝、赋值、析构。
- 默认初始化-依据位置,可能不进行初始化。值初始化-基本类型初始为0。对类类型来说都一样。
- 合成默认构造函数对未指定值的成员是默认初始化!因为不管且不在全局,因此数据不由elf定
- auto可以自动出指针,不过引用要加&
智能指针与new\delete
shared_ptr与unique_ptr都支持的操作:
使用动态内存原因:
- 不知道使用对象个数
- 不知道对象准确类型
- 多个对象见共享数据
shared_ptr类
智能指针也是模板,默认初始化为空指针。
shared_ptr独有的操作:
拷贝与赋值时都会记录有对少个指向相同对象,具体实现由库决定。一旦一个计数为0(所有导致递减的操作都可),它会自动释放管理的对象。
递减的操作如:sp的析构、赋值。
直接管理内存
动态分配的内存是默认初始化的,加()为值初始化,使用new还可以直接初始化、列表初始化。
因此称new为可选择初始化,不过类类型一定初始化了。
分配const的对象:
返回指向const的指针。
默认情况下,如果new不能分配所要求的内存空间,抛出bad_alloc异常。可以使用new(nothrow) int分配失败时返回空指针。
delete接受指针,销毁对象释放内存。指针必须是new分配的或者空指针,可释放const指针,非new或二次释放都未定义。
delete之后指针内容不变。
手动管理当心:
- 忘记delete,内存泄漏。
- 使用已经释放的对象
- 同一区域释放俩次,可能破坏空间
shared_ptr与new结合使用
可以用new返回的指针初始化智能指针,必须使用直接初始化,不能使用=构造,即不可转化。传参、返回时都要手动构造。
智能指针默认使用delete释放管理的对象。可自定义
sp的其它方法:
调用get返回的指针不能delete对象,否则一定会产生二次释放。因为智能指针保证指针在就可用。
智能指针和异常
函数正常结束或者发生异常,无论如何,局部对象都会被销毁—-这部分反编译还未研究。
因此智能指针在异常发生时仍可以释放,但自己管理的指针销毁不会影响对象。
因为这种某长生存期对象绑定某对象自动生存期的行为不仅发生在动态内存管理上,某些资源如网络连接,也需要这种管理方式。因此可以使用智能指针的自定义delete来管理资源。
智能指针注意:
- 不使用相同的内置指针初始化/reset多个智能指针
- 不delste get返回的指针
- 不使用get返回的指针初始化/reset另一个智能指针
unique_ptr
这种智能指针某时刻只能指向一个给定的对象。
特有操作:
不可赋值、拷贝uq,但可以拷贝赋值一个快销毁的unique_ptr。编译器分辨出并实行特殊拷贝…下一章介绍
uq与sq管理删除器的方式也不同,原因在16章
weak_ptr
这是一种不控制所指对象周期的智能指针,指向sp的对象。将wp绑定sp不会改变计数
主要用于不影响一个给定的sp生存期,但可以阻止用户访问一个不存在的企图。不可以直接解引用,要使用lock使用。
动态数组
new可以分配数组,allocator类是标准库实现。
new数组
分配动态数组的类必须有自己定义版本的拷贝、赋值、销毁,来管理内存。因为这些默认操作不会处理好内存
使用vector往往更好,更安全,效率也很高。
使用:
返回的是元素类型的指针。可以用[],但并不是数组类型。只能默认、值初始化,或者列表
普通数组长度不可为0,但动态数组可以。
释放要用deleate[] p;按逆序销毁释放。
库提供了可以管理new数组的up:unique_ptr
不支持访问运算符,但可以使用[]访问
sp不支持动态数组,想用必须自己加删除器。
allocator
头文件memory中的实现,将内存分配与对象构造分离。
一个allocator对象可以多次使用的,作为分配器。用指针分辨分配出的区域是哪一个
反汇编
|
|
X86-64
|
|
ARM-64
指令简记
arm的判断条件主要由每条指令的后缀判断的,这种条件是对指令通用的。
分析
|
|
这里是先用new分配内存,再对返回调用构造函数。不是在new内构造。
销毁也是先对this调用析构,再使用delete释放内存。不是在delete内析构的。此外,delete前自动判断了指针是否为null。