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相应的减一。

  1. 类继承中使用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);
  1. 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);
  1. 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操作没有线程安全。即

  1. shared_ptr 仅保证引用计数的正确性,在引用计数减为0之后,析构掉被管理对象;
  2. 在当前线程中进行赋值操作。不应在其他线程中进行赋值、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>(); }
};
  1. 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 进行处理, 使其有效. 具体见参考。

为什么

  1. 为什么需要 weak_ptr:编译期间解除A/B循环引用导致两者都不能释放内存,使用weak_ptr作为对方的引用 ref
  2. 为什么需要 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的更多相关文章

  1. stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

    stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...

  2. shared_ptr & weak_ptr

    shared_ptr <1> 类模板说明 namespace boost { class bad_weak_ptr: public std::exception; template< ...

  3. C++ 智能指针(shared_ptr/weak_ptr)原理分析

    其主要的类关系如下所示(省略相关的类模板参数): 图1 从上面的类图可以清楚的看出shared_ptr内部含有一个指向被管理对象(managed object)T的指针以及一个__shared_cou ...

  4. shared_ptr / weak_ptr 代码片段

    参考<<Boost程序库完全开放指南>> shared_ptr  类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...

  5. boost shared_ptr weak_ptr

    文档: http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/shared_ptr.htm shared_ptr构造有个原型 template< ...

  6. auto_ptr,unique_ptr,shared_ptr,weak_ptr

    http://mojijs.com/2016/08/218129/index.html http://www.cnblogs.com/lanxuezaipiao/p/4132096.html

  7. C++ 标准库智能指针

    整理一下c++中shared_ptr,weak_ptr,unique_ptr三种指针的使用案例和注意事项,让程序资源更加案例,在标准库中,需要包含<memory>,在boost库中, 一. ...

  8. 关于shared_ptr与weak_ptr的使用(good)

    shared_ptr是带引用计数的智能指针,可以说大部分的情形选择用shared_ptr不会出问题.那么weak_ptr是什么,应该怎么用呢? weak_ptr也是智能指针,但是比较弱,感觉没什么用. ...

  9. 智能指针shared_ptr新特性shared_from_this及weak_ptr

    enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...

  10. shared_ptr&scoped_ptr&weak_ptr

    [RAII - Resource Acquisition Is Initialization] 获得一个资源的时候,不管这个资源是对象.内存.文件句柄或者其它什么,你都要在一个对象的构造函数中获得它, ...

随机推荐

  1. 硬核剖析Redis单线程为什么那么快?

    (本文首发于"数据库架构师"公号,订阅"数据库架构师"公号,一起学习数据库技术,助力职业发展) Redis目前是使用率最高的内存库数据库,是企业应用开发的必备, ...

  2. 【项目实战】自备相机+IMU跑通Vins-Mono记录

    前言 初次接触SLAM,公司要求用自己的设备来跑通vinsmono这个程序,虽然已经跑通了别人的数据包,但是真正自己上手来运行这个程序,发现真的是困难重重,特意在此记载下来整个过程,以供大家参考. 我 ...

  3. .Net 不受 EAR 的约束

    NPUlrk :https://github.com/NPUlrk  同学在 dotnet/runtime 仓库提出了一共问题: https://github.com/dotnet/runtime/d ...

  4. 24_Java8

    Java8 一. Java8概述 Java8(又称JDK1.8)是Java语言开发的一个主要版本. Oracle公司于2014年3月18日发布Java8 支持Lambda表达式 函数式接口 新的Str ...

  5. vue禁用浏览器返回键

    mounted () { // 禁用浏览器返回键 history.pushState(null, null, document.URL); window.addEventListener('popst ...

  6. 局域网内搭建CentOS PHP 环境

    首先我们找到一台已经搭建好的CentOS,IP地址我就不说啦. 我们需要用到的几个工具,一个是SecureCRT用于远程连接,还有一个用于文件上传和下载就是filezilla 准备好了之后,我们就可以 ...

  7. POJ3041 小行星 (二分图匹配模板)

    学了这么久连模板都没有写过,我来补个坑...... 将行看成集合X,列看成Y,障碍看成是X到Y的一条边. 消除次数最少,等价于最小点覆盖问题,最小点覆盖=最大匹配数,跑一遍匈牙利就行了 #includ ...

  8. 洛谷P1036 [NOIP2002 普及组] 选数 (搜索)

    n个数中选取k个数,判断这k个数的和是否为质数. 在dfs函数中的状态有:选了几个数,选的数的和,上一个选的数的位置: 试除法判断素数即可: 1 #include<bits/stdc++.h&g ...

  9. Multi-View Intent Disentangle Graph Networks for Bundle Recommendation解读

    简要论述 bundle recommendation 的目的是向user推荐一个整体的bundle package about items.以前的模型捕获了user对item and item关联的偏 ...

  10. 齐博x1标签之无刷新显示更多

    示范代码如下: <div class="ListMoreInfos"> {qb:tag name="news_list_page_listdata02&quo ...