智能指针

一、智能指针类型&智能指针

1. 标准库提供了两种智能指针类型(来管理动态分配的对象)

2. 智能指针

  智能指针就是一个变量、一个对象,即智能指针类型的实例化(比如在整型 int 和变量 i 中,智能指针就类似 i)

3. 智能指针与指针

  智能指针的行为类似常规指针

  区别:智能指针负责自动释放所指向的对象

4. 两种智能指针的区别

智能指针类型 特点
shared_ptr 允许多个指针指向同一个对象
unique_ptr 该类型指针“独占”所指向的对象

 

二、shared_ptr

1. 形式

  • shared_ptr<T> p;

  解释:创建一个智能指针时,必须提供额外的信息——指针可以指向的类型

2. 默认初始化

  智能指针中保存着一个空指针

3. 初始化

  • shared_ptr<T> p = make_shared<T>(args)
  • shared_ptr<int> p1(new int (100))
  • shared_ptr<int> p2(p)

4. 每个 shared_ptr 都有一个关联的计数器(该计数器由指向同一对象的shared_ptr共享),也称引用计数(记录有多少个 shared_ptr 指向相同的对象)

  引用计数是shared_ptr所指向的对象的,即是相对智能指针所指向的对象而言的

  初始化一个shared_ptr对象后,其关联的计数器为1(也即该shred_ptr对象所指向的对象的引用计数为1)

  当一个shared_ptr对象的计数器变为0时,它就会自动释放自己所管理的对象(即释放内存)

5. 支持的操作(蓝色部分为shared_ptr和unique_ptr都支持的操作)

操作 说明

shared_ptr<T> sp

unique_ptr<T> up

空智能指针,可以指向类型为T的对象
p 将p作为一个条件判断,若p指向一个对象,则为true
*p 解引用p,获得它指向的对象
p->mem 等价于(*p).mem
p.get() 返回一个常规指针,该指针指向p所指的对象

swap(p, q)

p.swap(q)

交换p和q中的指针
make_shared<T>(args) 返回一个shared_ptr,指向一个动态分配的类型为T的对象,使用args初始化该对象
shared_ptr<T>p(q) p是shared_ptr q的拷贝,q中的指针必须能转化为T*
p = q p和q都是shared_ptr,所保存的指针必须能相互转换
p.use_count() 返回与p共享对象的智能指针数量
p.unique() 若p.use_count()为1,返回 true;否则返回 false

6. 备注

  在最后一个shared_ptr销毁前内存都不会释放

  计数器递增:用一个shared_ptr初始化另一个shred_ptr、将它当做参数传递给一个函数、作为函数的返回值

  计数器递减:给shared_ptr赋予一个新值、shared_ptr被销毁(例如一个局部的 shared_ptr离开其作用域)

7. 其他操作

操作 说明

T *q = new T

shared_ptr<T> p(q)

p管理内置指针q所指向的对象(该对象是new分配的内存)
shared_ptr<T> p(q, d) q指向的对象不是new分配的内存,p将使用可调用对象d来代替delete
shared_ptr<T> p(p2, d) p是shared_ptr p2的拷贝,p将使用可调用对象d来代替delete
shared_ptr<T> p(u) p从unique_ptr u那里接管了对象的所有权,将u置为空

p.reset()

p.reset(q)

p.reset(q, d)

若p是唯一指向其对象的shared_ptr,reset会释放此对象

q为内置指针,会令p指向q

将会调用d而不是delete来释放q

注:当将一个shared_ptr绑定到一个普通指针时,我们就将内存的管理责任交给了这个shared_ptr;当使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器

8. 使用示例

	int *p = new int(2);
    shared_ptr<int> sp = make_shared<int>(1);
    shared_ptr<int> sp2(p);
    shared_ptr<int> sp3(sp);
    cout << sp3.use_count() << endl;
    int *p2 = sp2.get();
    sp2.reset();
    sp3.reset(new int(5));

 

 

三、unique_str

1. 某个时刻,只能有一个 unique_ptr 指向一个给定对象

  当unique_str被销毁时,它所指向的对象也被销毁

2. 没有类似make_shared这样返回一个unique_str的函数

  定义一个unique_str时,需要将其绑定到一个new返回的指针上(和shared_ptr一样,初始化unique_str必须采用直接初始化形式)

3. 不支持普通的拷贝或赋值操作

  一个unique_str拥有它指向的对象(所以不能让其他的unique_str再指向它的对象啊)

4. 特有操作(与shared_ptr共享的操作参考上面)

操作 说明

unique_str<T> u1

unique_str<T, d> u2

空unique_str,可以指向类型为T的对象

u1使用delete来释放它的指针,u2使用一个类型为d的可调用对象来释放它的指针

unique_str<T, D> u(d) 同上,用类型为D的对象d代替delete
u = nullptr 释放u指向的对象,将u置为空
u.release()

返回指向u指向的对象的指针,将u置为空

release返回的指针用来:初始化另一个智能指针,或给另一个智能指针赋值

u.reset()

u.reset(q)

释放u指向的对象,将u置为空

q是内置指针,令u指向q指向的对象,并释放u原先指向的对象

注:释放对象即释放内存,将u置为空即“u = nullptr”

5. 向unique_ptr传递删除器

  • 类似shared_ptr,unique_ptr默认情况下用delete释放它指向的对象
  • 与shred_ptr一样,我们可以重载一个unique_ptr中默认的删除器(但unique_ptr管理删除器的方式与shared_ptr不同)

6. 使用示例

	int *p = new int(2);
    unique_ptr<int> up;
    unique_ptr<int> up2(p);
    up.reset(up2.release());
    unique_ptr<int> up3(up.release()); 

  

四、weak_ptr

1. 一种不控制所指向对象生存期的智能指针

  它指向由一个shared_ptr管理的对象

  将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数

  最后一个指向对象的shared_ptr被销毁,对象就会被释放,故weak_ptr指向的对象可能不存在

2. 创建一个weak_ptr时,要用一个shared_ptr来初始化它

    auto p = make_shared<int>(42);
    weak_ptr<int> wp(p);

3. 支持的操作

操作 说明
weak_ptr<T> w 空weak_ptr,可以指向类型为T的对象
weak_ptr<T> w(sp) 与shared_ptr sp指向相同对象的weak_ptr,T必须能转换为sp指向的类型
w = p p可以是一个shared_ptr或一个weak_ptr
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

4. 不能直接访问对象

  因为对象可能不存在,故必须调用lock,此函数检查weak_ptr指向的对象是否仍存在(如果存在,lock返回一个指向共享对象的shared_ptr)

5. 使用示例

	int *p = new int(2);
    shared_ptr<int> sp(new int(3));
    weak_ptr<int> wp(sp);
	weak_ptr<int> wp2, wp3;
	wp2 = wp; 
	wp3 = sp;
	wp.reset();		//将wp置为空 
	cout << wp.use_count() << endl;
	bool bl = wp.expired();
	shared_ptr<int> sp2 = wp.lock(); 

  

posted @ 2017-10-26 10:33  GGBeng  阅读(468)  评论(0编辑  收藏  举报