19使用shared_ptr管理具备共享所有权的资源:
shared_ptr通过共享所有权来管理生存周期,没有特定的shared_ptr拥有该对象当最后一个涉及到该对象的指针不再涉及到它时(即引用计数变为0),就会析构该对象
引用计数的影响:
- shared_ptr的尺寸是裸指针的两倍
- 引用计数的内存必须动态分配
- 引用计数的递增和递减是原子操作
- shared_ptr的移动操作快于复制操作,这是由于移动操作不涉及引用计数的操作
shared_ptr底层结构:
使用自定义析构器不会改变shared_ptr的尺寸,这是由于shared_ptr的特殊结构所致。
shared_ptr<T>由两部分组成:
- 指涉到T型别对象的指针
- 指涉到控制块的指针
控制块包括:
- 引用计数
- 其他数据(自定义析构器等)
控制块创建规则
- make_shared总会建一个控制块
- 由unique_ptr等专属所有权的指针创建一个shanred_ptr时会创建一个控制块
- 由裸指针生成一个shared_ptr时会创建一个控制块
控制块对指针的影响:
auto w = new int{ 10 };
shared_ptr<int>p1{ w };
shared_ptr<int>p2{ w };
形如此种操作就会导致为裸指针w生成两个控制块,即会析构两次指针,造成程序崩溃
shared_ptr使用建议:
应避免将裸指针作为参数生成shared_ptr,若必须使用裸指针生成,最好使用右值作为参数生成,即使用new
shared_ptr<int> p1(new int{});
此种方法会大大降低为一个裸指针生成两个控制块的概率。或使用
shared_ptr<int> p2(p1);
这样w与w1使用的是同一个控制块
请记住:
- std::shared_ptr提供和垃圾回收机制差不多方便的方法,来对任意的资源进行共享语义的生命周期管理。
- 比起std::unique_ptr,std::shared_ptr对象常常是它的两倍大,需要承担控制块的间接费用,并且需要原子的引用计数操作。
- 默认的资源销毁操作是通过delete进行的,但是自定义deleter是支持的。deleter的类型不会影响到std::shared_ptr的类型。
- 避免从原始指针类型的变量来创建std::shared_ptr。
Comments NOTHING