(C++) C++ 中 shared_ptr weak_ptr
shared_ptr

std::shared_ptr<int> sp1 = new int(); // shared count = 1, weak count = 0
std::shared_ptr<int> sp2(sp1); // shared count = 2, weak count = 0
std::shared_ptr<int> sp3 = sp2; // shared count = 3, weak count = 0
std::weak_ptr<int> wp1(sp1); // shared count = 3, weak count = 1
std::weak_ptr<int> wp2(wp1); // shared count = 3, weak count = 2
std::weak_ptr<int> wp3 = wp2; // shared count = 3, weak count = 3
shared_ptr weak_ptr 使用 reset 或者指向另一个 managed object导致 shared count或weak count相应的减一。
- 类继承中使用shared_ptr
class Base {};
class Derived : public Base {};
......
shared_ptr<Derived> dp1(new Derived);
shared_ptr<Base> bp1 = dp1;
shared_ptr<Base> bp2(dp1);
shared_ptr<Base> bp3(new Derived);
- casting shared_ptr
shared_ptr<Base> base_ptr (new Base);
shared_ptr<Derived> derived_ptr;
// if static_cast<Derived *>(base_ptr.get()) is valid, then the following is valid:
derived_ptr = static_pointer_cast<Derived>(base_ptr);
- make_shared
使用shared_ptr = new int(),会导致两次内存分配:int对象的内存分配跟shared_ptr内部的 manager object 一次内存分配。make_shared 对此进行了优化,一次性分配 int + manager object 内存空间大小。
make_shared 用法:
shared_ptr<Thing> p (make_shared<Thing>(42, "I'm a Thing!"));
shared_ptr<Base> bp(make_shared<Derived1>()); // shared_ptr中的 template参数与make_shared中的tmeplate参数可以不一样(继承关系)
使用 weak_ptr
void do_it(weak_ptr<Thing> wp){
shared_ptr<Thing> sp = wp.lock(); // get shared_ptr from weak_ptr
if(sp)
sp->defrangulate(); // tell the Thing to do something
else
cout << "The Thing is gone!" << endl;
}
也可以直接从weak_ptr构建shared_ptr,这个时间如果weak_ptr过期(通过 weak_ptr::expired() 可以查询),则抛出异常:
void do_it(weak_ptr<Thing> wp){
shared_ptr<Thing> sp(wp); // construct shared_ptr from weak_ptr
// exception thrown if wp is expired, so if here, sp is good to go
sp->defrangulate(); // tell the Thing to do something
}
shared_ptr 线程安全
shared_ptr / weak_ptr 中的引用计数是线程安全的(atomic/memory barrier);但是跨线程赋值操作、reset操作没有线程安全。即
- shared_ptr 仅保证引用计数的正确性,在引用计数减为0之后,析构掉被管理对象;
- 在当前线程中进行赋值操作。不应在其他线程中进行赋值、reset操作;
enable_shared_from_this 及 shared_from_this
定义一个类,实现内存自动管理。两次调用 get 返回的是两个不同的shared_ptr,将导致同一个BadThing对象两次析构。
class BadThing {
public:
BadThing() = default;
shared_ptr<BadThing> get() { return std::make_shared<BadThing>(); }
};
- enable_shared_from_this的实现
// enable_shared_from_this的实现
// 基于(/usr/include/c++/7.3.0/bits/shared_ptr.h)
// 此代码是对gcc实现的简化版本, 仅作为描述原理用.
template<typename T>
class enable_shared_from_this
{
public:
shared_ptr<T> shared_from_this()
{
return shared_ptr<T>(this->weak_this);
}
shared_ptr<const T> shared_from_this() const
{
return shared_ptr<const T>(this->weak_this);
}
private:
template<typename>
friend class shared_ptr;
template<typename T1>
void _M_weak_assign(T1* p, const shared_count<>& n)
{
weak_this._M_assign(p, n);
}
mutable weak_ptr<T> weak_this;
};
enable_shared_from_this 类中定义了一个 weak_ptr, 起到了上文提到的从obj指针生成 shared_ptr 对象的作用. 按照先前的原理, 我们可能认为是在obj初始化的时候, 同时对 weak_this 进行初始化, 但是在这段代码里显然没有对 weak_this 进行任何初始化工作(原始代码里也没有, gcc为什么不这样实现呢? 这是因为当对象没有由智能指针管理时, 这些操作是没有必要的. 所以应该把这个任务交给 shared_ptr). 第一个持有 Good 对象 g_obj 的 shared_ptr sp1 会对 g_obj 的 weak_this 进行处理, 使其有效. 具体见参考。
为什么
- 为什么需要 weak_ptr:编译期间解除A/B循环引用导致两者都不能释放内存,使用weak_ptr作为对方的引用 ref;
- 为什么需要 enable_shared_from_this:特别的,在类内部需要调用函数(如创建线程等异步处理将自身作为参数);
参考
Using C++11’s Smart Pointers PDF
enable_shared_from_this类的作用和实现
std::shared_ptr std::weak_ptr 线程安全性
从 shared_from_this() 谈智能指针 weak_ptr 和 shared_ptr 的实现
(C++) C++ 中 shared_ptr weak_ptr的更多相关文章
- stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结
stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...
- shared_ptr & weak_ptr
shared_ptr <1> 类模板说明 namespace boost { class bad_weak_ptr: public std::exception; template< ...
- C++ 智能指针(shared_ptr/weak_ptr)原理分析
其主要的类关系如下所示(省略相关的类模板参数): 图1 从上面的类图可以清楚的看出shared_ptr内部含有一个指向被管理对象(managed object)T的指针以及一个__shared_cou ...
- shared_ptr / weak_ptr 代码片段
参考<<Boost程序库完全开放指南>> shared_ptr 类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...
- boost shared_ptr weak_ptr
文档: http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/shared_ptr.htm shared_ptr构造有个原型 template< ...
- auto_ptr,unique_ptr,shared_ptr,weak_ptr
http://mojijs.com/2016/08/218129/index.html http://www.cnblogs.com/lanxuezaipiao/p/4132096.html
- C++ 标准库智能指针
整理一下c++中shared_ptr,weak_ptr,unique_ptr三种指针的使用案例和注意事项,让程序资源更加案例,在标准库中,需要包含<memory>,在boost库中, 一. ...
- 关于shared_ptr与weak_ptr的使用(good)
shared_ptr是带引用计数的智能指针,可以说大部分的情形选择用shared_ptr不会出问题.那么weak_ptr是什么,应该怎么用呢? weak_ptr也是智能指针,但是比较弱,感觉没什么用. ...
- 智能指针shared_ptr新特性shared_from_this及weak_ptr
enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...
- shared_ptr&scoped_ptr&weak_ptr
[RAII - Resource Acquisition Is Initialization] 获得一个资源的时候,不管这个资源是对象.内存.文件句柄或者其它什么,你都要在一个对象的构造函数中获得它, ...
随机推荐
- re.sub()用法
原文链接:https://blog.csdn.net/jackandsnow/article/details/103885422
- SpringBoot Xml转Json对象
一.导入需要的依赖 <dependency> <groupId>maven</groupId> <artifactId>dom4j</artifa ...
- Elasticsearch:Elasticsearch中的refresh和flush操作指南
在今天的文章里,我们来主要介绍一下Elasticsearch的refresh及flush两种操作的区别.如果我们从字面的意思上讲,好像都是刷新的意思.但是在Elasticsearch中,这两种操作是有 ...
- Elasticsearch: 使用URI Search
在Elasticsearch中,我们可以使用_search终端进行搜索.这个在我之前的文章 "开始使用Elasticsearch (2)" 中有很多的描述.针对这种搜索,我们可以使 ...
- Linux下多线程创建
1.pthread_create Linux中线程创建用pthread_create函数 #include <pthread.h> int pthread_create( pthread_ ...
- P1600 [NOIP2016 提高组] 天天爱跑步 (树上差分)
对于一条路径,s-t,位于该路径上的观察员能观察到运动员当且仅当以下两种情况成立:(d[ ]表示节点深度) 1.观察员x在s-lca(s,t)上时,满足d[s]=d[x]+w[x]就能观察到,所以我们 ...
- POJ3280 Cheapest Palindrome (区间DP)
dp[i][j]表示将字符串子区间[i,j]转化为回文字符串的最小成本. 1 #include<cstdio> 2 #include<algorithm> 3 #include ...
- 详解商业智能“前世今生”,“嵌入式BI”到底是如何产生的?
嵌入式分析是使任何应用程序或用户更容易获得数据分析和商业智能的技术. 商业智能是通过分析业务数据辅助决策获取数据背后的 0信息. 商业智能软件和技术包含了报表查询,OLAP,数据挖掘及高级数据分析,最 ...
- Java学习之路:Dos命令
2022-10-08 10:25:42 (一)打开CMD的方式 开始+系统+命令提示符 Win+R 输入cmd打开控制台 在任意的文件夹下面,按住Shift+鼠标右键,点击在此打开命令行窗口 资源 ...
- 基于纯前端类Excel表格控件实现在线损益表应用
财务报表也称对外会计报表,是会计主体对外提供的反映企业或预算单位一定时期资金.利润状况的会计报表,由资产负债表.损益表.现金流量表或财务状况变动表.附表和附注构成.财务报表是财务报告的主要部分,不包括 ...