1.智能指针为什么存在?
因为C++没有自动回收内存的机制,因此每一次new出来的动态内存必须手动delete回去。因此智能指针可以解决这个问题。
2.智能指针的大致描述是什么?
智能指针:自动负责释放所指向的对象,实际上它利用了栈的机制,每一个智能指针都是一个模板类,调用智能指针实际上是创建了一个智能指针的对象,对象生命周期到达尽头的时候,会自动调用智能指针的析构函数,在析构函数里,释放掉它管理的内存,从而避免手动delete。
3.三大类智能指针是什么?
指针 | 简要描述 |
---|---|
shared_ptr | 允许多个指针指向同一个对象 |
unique_ptr | 独占所指向的对象 |
weak_ptr | shared_ptr的弱引用 |
shared_ptr描述(in memory):
shared_ptr是一个标准的共享所有权的智能指针,就是允许多个指针指向同一对象,shared_ptr对象中不仅有一个指针指向某某(比如 int型,以下也拿int类型举例)对象,还拥有一个引用计数器,代表一共有多少指针指向了那个对象。
shared_ptr自动销毁所管理的对象
每当创建一个shared_ptr的对象指向int型数据,则引用计数器值+1,每当销毁一个shared_ptr对象,则-1.当引用计数器数据为0时,shared_ptr的析构函数会销毁int型对象,并释放它占用的内存。
shared_ptr和new的配合使用
接受指针作为参数的智能指针的构造函数是explicit类型,意味着只能以初始化的方式定义。
定义方法:
shared_ptr<int> p1;
//被初始化成为一个空指针
shared_ptr<int> p2 (new int(4));
//指向一个值是4的int类型数据
shared_ptr<int> p3 = new int(4);
//错误,必须直接初始化
不能混合使用普通指针和智能指针,因为智能指针不是单纯的赤裸裸的指针
void process(shared_ptr<int> ptr){
//受到参数值传递的影响,ptr被构造并且诞生,执行完函数块后被释放
}
int *x(new int (43));
//x是一个普通的指针
process(x);
//错误,int * 不能转换成shared_ptr<int>类型
process(shared_ptr<int> x);
//临时创造了x,引用数+1,执行完process之后,引用数-1
int j = *x;
//x是一个空悬指针,是未定义的
不能使用get()函数对智能指针赋值或初始化
原因:get()函数得到的是共享对象的地址,是内置指针,指向智能指针管理的对象,而智能指针不仅仅包含地址,两个东西不是一个类型的,也不能彼此包含,因此不能这样做。
同样,把get()返回值 绑定到智能指针上也是错误的
如下:
shared_ptr<int> p (new int(22));
int *q = p.get();
//语义没问题
{
shared_ptr<int> (q);
//意味着q被绑定,!!!!引用计数器还是1!!!!
//如果这个被执行,程序块结束以后q和q所指的内容被销毁,则代表着以后执行(*p)的解引用操作,就成了未定义的了。
}
int r = *p;
//已经不对了,因为p指向的内存已经在刚才那个代码块里被q释放了
shared_ptr的一些操作
shared_ptr<T> p;
//空智能指针,可指向类型是T的对象
if(p)
//如果p指向一个对象,则是true
(*p)
//解引用获取指针所指向的对象
p -> number == (*p).number;
p.get();
//返回p中保存的指针
swap(p,q);
//交换p q指针
p.swap(q);
//交换p,q指针
make_shared<T>(args)
//返回一个shared_ptr的对象,指向一个动态类型分配为T的对象,用args初始化这个T对象
shared_ptr<T> p(q)
//p 是q的拷贝,q的计数器++,这个的使用前提是q的类型能够转化成是T*
shared_pts<T> p(q,d)
//p是q的拷贝,p将用可调用对象d代替delete
//上面这个我其实没懂,也没有查出来这个的意思
p =q;
//p的引用计数-1,q的+1,p为零释放所管理的内存
p.unique();
//判断引用计数是否是1,是,返回true
p.use_count();
//返回和p共享对象的智能指针数量
p.reset();
p.reset(q);
p.reset(q,d);
//reset()没懂,这个以后再来补充吧
unique_ptr描述(in memory):
与shared_ptr不同,某一时刻,只能有一个unique_ptr指向一个给定的对象。因此,当unique_ptr被销毁,它所指的对象也会被销毁。
unique_ptr的初始化必须采用直接初始化
unique_ptr<string> p(new string("China"));
//没问题
unique_ptr<string> p (q);
//错误,不支持拷贝
unique_ptr<string> q;
q = p;
//错误,不支持赋值
unique_ptr的一些操作:
unique_ptr<T> p;
//空智能指针,可指向类型是T的对象
if(p)
//如果p指向一个对象,则是true
(*p)
//解引用获取指针所指向的对象
p -> number == (*p).number;
p.get();
//返回p中保存的指针
swap(p,q);
//交换p q指针
p.swap(q);
//交换p,q指针
unique_ptr<T,D>p;
//p使用D类型的可调用对象释放它的指针
p = nullptr;
//释放对象,将p置空
p.release();
//p放弃对指针的控制,返回指针,p置数空
p.reset();
//释放p指向的对象
p.reset(q);
//让u指向内置指针q
unique_ptr作为返回值是可以的,这样可以拷贝或者赋值
weak_ptr描述(in memory)
weak_ptr是一种不控制所指向对象生存期的智能指针,指向shared_ptr管理的对象,但是不影响shared_ptr的引用计数。它像shared_ptr的助手,一旦最后一个shared_ptr被销毁,对象就被释放,weak_ptr不影响这个过程。
weak_ptr的一些操作:
weak_ptr<T> w(sp);
//定义一个和shared_ptr sp指向相同对象的weak_ptr w,T必须能转化成sp指向的类型
w = p;
//p是shared_ptr或者weak_ptr,w和p共享对象
w.reset();
//w置为空
w.use_count();
//计算与w共享对象的shared_ptr个数
w.expired();
//w.use_count()为0,返回true
w.lock();
//w.expired()为true,返回空shared_ptr,否则返回w指向对象的shared_ptr