auto_ptr
auto_ptr是C++标准库中为了解决资源泄露的问题提供的一个智能指针模板,是一种简单的智能指针
功能:动态分配对象以及当对象不再需要时自动执行清理
实现原理:在构造的时候获取资源,在析构的时候释放资源,并进行相关指针操作的重载,使用起来和普通指针类似,但由于其构造函数声明为explicit,因此不能通过隐式转换来构造,只能显示调用构造函数
auto_ptr<string> pstr(new string("abc")); // succeess
auto_ptr<string> pstr = new string("abc"); // error
特性及注意事项:
①auto_ptr没有考虑引用计数,因此一个对象只能由一个auto_ptr所拥有,在给其他auto_ptr赋值,参数传递的时候,会转移这种拥有关系
②使用auto_ptr作为成员变量,取代普通指针,以避免资源泄漏。防止构造函数产生了异常,导致析构函数不会调用。
③auto_ptr不能共享所有权
④auto_ptr不能指向数组,因为数组在析构的时候需要调用delete[],而它只会调用delete
⑤auto_ptr不能作为容器对象,防止在进行拷贝、赋值等操作时,传递所有权
属于memory头文件,需#include
unique_ptr
unique_ptr独占所指向的对象,同一时刻只能有一个,它只能移动。由于每个unique_ptr对象都是原始指针的唯一所有者,因此在其析构函数中它直接删除关联的指针,不需要任何参考计数
unique_ptr具有->和*运算符重载符,因此它可以像普通指针一样使用
unique_ptr 指向给定对象,定义于memory中,命名空间为std
unique_ptr 不支持拷贝和赋值.
shared_ptr
shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象. 定义在 memory 文件中(非memory.h), 命名空间为 std
shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的), 在使用引用计数的机制上提供了可以共享所有权的智能指针, 当然这需要额外的开销
shared_ptr 对象除了包括一个所拥有对象的指针外, 还必须包括一个引用计数代理对象的指针
时间上的开销主要在初始化和拷贝操作上, *和->操作符重载的开销跟auto_ptr是一样
开销并不是我们不使用shared_ptr的理由, 永远不要进行不成熟的优化, 直到性能分析器告诉你这一点
share_ptr使用注意事项:
(1)、不要把一个原生指针给多个shared_ptr管理;
(2)、不要把this指针给shared_ptr;
(3)、不要在函数实参里创建shared_ptr;
(4)、不要不加思考地把指针替换为shared_ptr来防止内存泄漏,shared_ptr并不是万能的,而且使用它们的话也是需要一定的开销的;
(5)、环状的链式结构shared_ptr将会导致内存泄漏(可以结合weak_ptr来解决);
(6)、共享拥有权的对象一般比限定作用域的对象生存更久,从而将导致更高的平均资源使用时间;
(7)、在多线程环境中使用共享指针的代价非常大,这是因为你需要避免关于引用计数的数据竞争;
(8)、共享对象的析构器不会在预期的时间执行;
(9)、不使用相同的内置指针值初始化(或reset)多个智能指针;
(10)、不delete get()返回的指针;
(11)、不使用get()初始化或reset另一个智能指针;
(12)、如果使用get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了;
(13)、如果你使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器。
weak_ptr
weak_ptr 也是以模板类的方式实现的. 定义在 memory 文件中(非memory.h), 命名空间为 std
weak_ptr是弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。所以weak_ptr通常不单独使用(没有实际用处),只能配合shared_ptr类型指针搭配使用,同时也不影响所指对象被释放
借助weak_ptr类型指针,我们可以获取shared_ptr指针的一些状态信息,比如有多少指向相同的shared_ptr指针、shared_ptr指针指向的堆内存是否已经被释放等
weak_ptr模板类中没有重载*和->运算符,所以weak_ptr类型指针只能访问所指的堆内存,而无法修改它
scoped_ptr
scoped_ptr与auto_ptr类似,包装了new操作符在堆上分配的动态对象,能够保证动态创建的对象在任何时候都可以被正确删除。但最大的区别就是它不能转让管理权,即scoped_ptr禁止用户进行拷贝与赋值
实现方法:将拷贝构造函数与赋值运算符重载的访问限定符设置为private,并且只给出其声明:
class ScopedPtr{
private:
ScopedPtr(const ScopedPtr& sp);
ScopedPtr& operator(const ScopedPtr& sp);
};