智能指针
有三个智能指针,auto_ptr(弃用)、unique_ptr、shared_ptr.
智能指针可以自动跟踪动态内存,在其过期时自动释放。
#include<memory>
一、shared_ptr
用于new创建的对象,而不适用于new[]创建的对象,
用于多个指针共享一个地址的情况。
默认初始化的智能指针中保存着一个空指针。
1.1 make_shared函数
最安全的分配和使用动态内存的方法是调用make_shared函数;
通常使用auto定义一个对象来保存make_shared的结果,
注意,auto只能用来初始化单个值,因此不能用来初始化列表。
auto p=make_shared<int>(42);//p指向的对象只有p一个引用者
auto q(p);//p和q指向相同的对象,此对象有两个使用者。
不能将一个内置指针隐式转化为一个智能指针:
shared_ptr<int>p1=new int(1024);//错误,必须使用直接初始化方式
shared_ptr<int>p2(new int(1024));//正确,使用了直接初始化方式
1.2 智能指针不能使用动态生存期资源的类:
- 程序不知道自己需要使用多少对象;
- 程序不知道所需对象的准确类型;
- 程序需要在多个对象之间共享数据。
1.3 智能指针使用规范
- 不使用相同的内置指针值初始化(或reset)多个智能指针;
- 不delete get()返回的指针;
- 不使用get()初始化或reset另一个智能指针;
- 如果你使用get返回的指针,记住当最后一个对应的指针销毁后,你的指针就变为无效了;
- 如果你使用智能指针管理的资源不是new分配的内存,记住传递给他一个删除器。
二、unique_ptr
用于只存留一个指针指向最后地址的情况,同时unique_ptr有指向new[]的版本。
控制权转移。
unique_ptr必须使用直接初始化方式:
unique_ptr<double> p1;
unique_ptr<int> p2(new int(42));
unique_ptr的“独占”是指:不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr。例如:
std::unique_ptr<int> p (new int);
std::unique_ptr<int> q = p; //error
但是unique_ptr允许通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,注意,这时它本身就不再拥有原来指针的所有权了。
std::unique_ptr<int> p (new int);
std::unique_ptr<int> q = std::move(p); //ok
三、操作
3.1 shared_ptr和unique_ptr都支持的操作
操作 | 作用 |
---|---|
shred_ptr |
空智能指针,可以指向类型为T的对象 |
p->mem | 等价于(*p).mem |
p.get() | 返回p中保存的指针 |
swap(p,q),p.swap(q) | 交换p和q中的指针 |
3.2 shared_ptr中独有的操作
操作 | 作用 |
---|---|
make_shared |
初始化一个智能指针 |
shared_ptr |
使用q初始化p,会增加计数 |
p=q | q必须能转化为shared_ptr类型 |
p.uniqe() | 判断计数是否为1,是1返回true |
p.use_count() | 返回与p共享对象的智能指针数量 |
3.3 unique_ptr中独有的操作
操作 | 作用 |
---|---|
unique_ptr(T) u1 , unique_ptr(T,D)u2 | 空智能指针,u1使用delete释放指针,u2使用D释放指针 |
unique_ptr(T,D)u(d) | 空指针,使用类型为D的对象d代替delete |
u=nullptr | 释放u指向的对象,将u置为空 |
u.release() | 释放u的控制权,将u置为空 |
u.reset() | 释放u指向的对象 |
u.reset(q),u.reset(nullptr) | 如果提供了内置指针q,令u指向这个对象;否则将u置为空 |
四、weak_ptr
弱指针用于避免share_ptr循环引用的问题。
由于弱引用不更改引用计数,类似普通指针,只要把循环引用的一方使用弱引用,即可解除循环引用。
虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。因此,不要认为只要使用了智能指针便能杜绝内存泄漏。毕竟,对于C++来说,由于没有垃圾回收机制,内存泄漏对每一个程序员来说都是一个非常头痛的问题。
五、动态数组
大多数情况下使用动态数组都是使用vector来实现。
标准库提供了一个可以管理new分配的数组的unique_ptr版本。
unique_ptr<int[10]>up(new int [10]);//初始化
up.release();//自动用delete[]销毁其指针
5.1 allocator类
TODO:)
其他
如ps是一个智能指针对象,则可以对它:
解除引用*ps
访问结构成员ps->index
将它赋给同类型常规指针
unique_ptr为右值时,可将其赋给shared_ptr
unique_ptr赋给另一个unique_ptr时,需要使用移动构造函数std::move()
参考链接:
https://www.cnblogs.com/wuyepeng/p/9741241.html
https://www.cnblogs.com/TianFang/archive/2008/09/20/1294590.html