1、动态内存与智能指针
shared_ptr类
支持的操作
make_share函数
make_share定义在memory头文件中,作用是分配一个对象并初始化它,返回指向此对象的shared_ptr指针
使用示例
shared_ptr的拷贝和赋值
可认为每个shared_ptr都有一个引用计数
无论何时拷贝一个shared_ptr,计数器都会递增
当给一个shared_ptr赋新值或是shared_ptr被销毁时,计数器会递减
当一个shared_ptr的计数器变为0时,它会自动释放自己所管理的对象
示例
shared_ptr自动销毁所管理的对象
shared_ptr自动销毁时是通过调用析构函数实现的
直接管理内存
使用new动态分配和初始化对象
new无法为其分配的对象命名,而是返回一个指向该对象的指针
默认情况下,动态分配的内存是默认初始化的,对于着内置类型和组合类型来说,值是未定义的,对于类类型对象来说,动态分配内存将使用默认构造函数进行初始化
初始化动态分配的对象的方式:
1、直接初始化
2、传统的构造方式
3、新标准下,可使用列表初始化
若提供一个括号包围的初始化器,则可用auto推断我们想要分配的对象的类型
只有当括号中只有一个初始化器时才可以使用auto
动态分配const对象
内存耗尽
new失败会抛出bad_alloc异常
可向new传一个nothrow参数,这样new失败就会返回一个空指针
shared_ptr和new结合使用
接受指针参数的智能指针的构造函数是explicit的,所以不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式
同样道理,一个返回shared_ptr的函数不能返回内置指针
定义和改变shared_ptr的其它方法
不要混合使用普通指针与智能指针
也不要使用get初始化另一个智能指针或为智能指针赋值
智能指针和异常
使用智能指针,即使程序发生异常,内存也会被释放掉,但使用new-delete,则不一定
使用我们自己的释放操作
当一个shared_ptr被销毁时,默认对指针进行delete操作
当我们创建一个shared_ptr时,可以传递一个指向删除函数的参数,当shared_ptr被销毁时就不会进行delete,而是调用指定的函数
unique_ptr
与shared_ptr不同,某一时刻只能有一个unique_ptr指向对象,因此unique_ptr不支持普通的拷贝和赋值操作
unique_ptr操作
可通过release和reset将指针所有权转移
传递unique_ptr和返回unique_ptr
不拷贝unique_ptr有一个例外:可以拷贝或赋值一个即将要被销毁的unique_ptr,最常见例子就是从函数返回一个unique_ptr
向unique_ptr传递删除器
weak_ptr
weak_ptr是一个不控制对象生存周期的智能指针,它绑定到一个shared_ptr上不会改变shared_ptr的引用计数
相关操作
2、动态数组
new和数组
除用new[ ]外,还可用表示数组类型的类型别名来分配数组
示例
分配一个数组会得到一个元素类型的指针
初始化动态分配对象的数组
可以对数组中的元素进行值初始化,方法是在大小后面加一对小括号
示例
新标准中,还可提供元素初始化器的花括号列表
示例
智能指针和动态数组
用unique_ptr管理动态数组,需要在对象类型后加一个[ ]
指向动态数组的unique_ptr不支持成员访问运算符(点和箭头运算符),可用下标进行访问
相关操作
与unique_ptr不同,shared_ptr不支持直接管理动态数组,若想管理,需提供自己定义的删除器
示例
allocator类
一般情况下,将内存分配和对象构造组合在一起可能造成不必要的浪费
如
allocator类一般定义在头文件memory中,是一个模板
相关操作及算法
allocator分配未构造的内存
使用时需先用allocate申请内存,然后才能使用construct构造对象
归还时需先用destroy,再用deallocate
拷贝和填充未初始化的内存的算法