现代C++为了解决内存泄露以及资源回收等问题,引入了智能指针的概念。在日常的C++实践中也是高频使用。
本文是在实践过程中,对现代C++中的智能指针进行的一个稍微全面的总结。
概念及使用
std::shared_ptr也即智能指针,采用RAII手法,是一个模版对象。std::shared_ptr表示某一个资源的共享所有权。
可以通过如下两种方式创建std::shared_ptr对象
auto p = shared_ptr<T>(new T);
auto p = make_shared<T>(T{});
实现原理
此处以如下代码为例,讲解std::shared_ptr的实现原理(仅给出便于理解的感性认知,源码层面的讲解不在本文范围之内).
#include <iostream>
#include <memory>
using std::cout;
int main() {
auto p = std::make_shared<int>(4);
auto p1 = std::shared_ptr<int>(new int(4));
cout << *p << *p1 << "\n";
return 0;
}
上述对象p的内存布局如下所示
关于上述实现原理图,需要作如下说明
- std::shared_ptr本身只包含两个对象:指向控制块对象的Ctr指针和一个指向其管理的资源的指针Ptr
- 当采用std::shared_ptr
(new T{})这种形式创建智能指针时,其控制块对象中会包含一个M_ptr成员,该指针指向智能指针所管理的资源 - 控制块对象至少会包含use_count(引用计数), weak_count(弱引用计数), 以及其他数据这三部分内容
再来看看,针对对象p1的内存布局
关于上述实现原理图,需要作如下说明
- 当采用std::make_shared创建智能指针时,其控制块对象和被管理资源被存放在同一个内存块中
- 当采用std::make_shared创建智能指针时,其控制块对象中,不会包含M_ptr成员(该成员指向智能指针所管理的资源)
NOTE:建议优先考虑std::make_shared
方式创建shared_ptr对象
使用场景
本小节主要讲解shared_ptr的几种使用场景包括可能存在的问题。
拷贝和移动
此处探讨shared_ptr 的拷贝和移动时,其引用计数的变化。
此处通过如下代码讲解
#include <iostream>
#include <memory>
int main() {
auto p = std::make_shared<int>(4);
auto p1 = p;
std::cout << "p use_count: " << p.use_count() << "\n";
auto p2 = std::move(p);
std::cout << "p1 use_count: " << p1.use_count() << "\n";
std::cout << "p use_count: " << p.use_count() << "\n";
return 0;
}
上述输出结果为
p use_count: 2
p1 use_count: 2
p use_count: 0
关于上述原因:
shared_ptr的拷贝构造函数会增加引用计数,使用move()移动语义将左值转换为右值,调用shared_ptr的移动构造函数,移动构造函数是一个浅拷贝的操作,不会增加引用计数。
并且使用move()一个shared_ptr是移动而不是复制,可以避免增加数量再减少数量的两个原子操作,可以节省相对耗时的原子操作。
NOTE:如果非必要建议使用移动构造shared_ptr
Guideline: Don’t pass a smart pointer as a function parameter unless you want to use or manipulate the smart pointer itself, such as to share or transfer ownership.
Guideline: Express that a function will store and share ownership of a heap object using a by-value shared_ptr parameter.
Guideline: Use a non-const shared_ptr& parameter only to modify the shared_ptr. Use a const shared_ptr& as a parameter only if you’re not sure whether or not you’ll take a copy and share ownership; otherwise use widget* instead (or if not nullable, a widget&).
除非您要使用或操纵智能指针本身,例如共享或转让所有权,否则不要将智能指针作为函数参数传递。准则:表示函数将使用按值shared_ptr参数存储和共享堆对象的所有权。准则:仅使用非常量shared_ptr&参数来修改shared_ptr。仅在不确定是否要复制并共享所有权时,才使用const shared_ptr&作为参数。否则,请改用widget *(或者,如果不能为null,则使用widget&)。
标签:std,auto,Modern,C++,智能,shared,ptr,指针 From: https://www.cnblogs.com/happinesspills/p/16831524.html