shared_ptr数据结构
shared_ptr 是引用计数型(reference counting)智能指针,几乎所有的实现都采用在堆(heap)上放个计数值(count)的办法。
具体来说,shared_ptr<Foo> 包含两个成员,一个是指向 Foo 的指针 ptr,另一个是 ref_count 指针,指向堆上的 ref_count 对象。ref_count 对象有多个成员,具体的数据结构如图所示,其中 deleter 和 allocator 是可选的。
如果再执行 shared_ptr<Foo> y = x; 那么对应的数据结构如下。
但是 y=x 涉及两个成员的复制,这两步拷贝不会同时(原子)发生。
既然 y=x 有两个步骤,如果没有 mutex 保护,那么在多线程里就有 race condition。
Shared_ptr使用构造函数和make_shared的区别
shared_ptr构造函数会执行两次内存申请,而make_shared只执行一次
shared_ptr在实现的时候内部会有一个控制块(计数器,用来管理数据)和一个指针指向数据,因此在执行的时候首先会申请数据的内存,然后申请控制块,因此是两次内存申请。
而make_shared则是执行一次内存申请,将数据与控制块的申请放到一起。
make_shared的缺点
因为make_shared只申请一次内存,因此控制块和数据块在一起,只有当控制块中不再使用时,内存才会释放,但是weak_ptr却使得控制块一直在使用。
由于make_shared()使得数据和控制块一起分配,自然只要有weak_ptr指向了控制块,就不会释放整块内存了。
weak_ptr
weak_ptr是用来指向shared_ptr,用来判断shared_ptr指向的数据内存是否还存在了(通过方法lock)
当不存在的时候,会返回一个空的shared_ptr,weak_ptr在指向shared_ptr的时候,并不会增加count
weak_ptr主要有两个用途:
- 用来记录对象是否存在
- 用来解决shared_ptr循环引用问题