本文基于C++标准库源码分析shared_ptr,旨在搞清楚shared_ptr是什么,线程安全性等,目标能够安全的使用智能指针。

(一)shared_ptr是一个类。

首先可以确定的是shared_ptr是一个类,那么就可以通过类的内存空间来从本质上分析它的结构。

通过sizeof()一个shared_ptr可以观察到它的大小为8个字节,然后追踪源代码发现它继承一个__shared_ptr类,这个类包含了两个组件:一个指针和一个类。

_M_ptr很好理解,就是一个指向你所保护的对象的指针(4字节)。

那么重点观察__shared_count<_Lp>是个什么东西。我们继续追踪源代码,可以看到__shared_count包含一个_Sp_counted_base类型的指针(4字节)

而这个_Sp_coutned_base类又有什么呢? 两个int类型的记数变量。

一个记录引用计数,一个记录weak_ptr的数量。现在通过层层剖析,我们可以画出shared_ptr的内存空间,如图所示:

而shared_ptr的构造函数也就是主要构造这两个东西,我们把重点放在计数类的构造上,看看它是如何实现线程安全的引用计数的。

首先_Sp_count_base模板类型_Lp是一个枚举,分别是_S_single、_S_mutex、_S_atomic。分别对应不同的计数方法,我们重点来看原子操作:

非常经典的CAS操作,__count为当前引用数,如果当前引用计数为0则抛出异常。利用do-while实现安全的操作。while里的函数原型为:

bool__atomic_compare_exchange_n (type *ptr, type *expected, type desired,boolweak,intsuccess_memorder,intfailure_memorder);

expected就是旧值,desired就是我们要+1后得到的新值,如注释所说,与旧值对比如果没变化则+1,否则就会返回false不断循环。

本篇主要讲解shared_ptr这个类的本质,简单介绍了它的两个组件,以及计数类是如何用原子操作实现线程安全的计数,下篇我们讲解shared_ptr的线程安全性,探讨多线程下对shared_ptr的读写安全问题。

深入理解智能指针之shared_ptr(一)的更多相关文章

  1. C++ | 再探智能指针(shared_ptr 与 weak_ptr)

    上篇博客我们模拟实现了 auto_ptr 智能指针,可我们说 auto_ptr 是一种有缺陷的智能指针,并且在C++11中就已经被摈弃掉了.那么本章我们就来探索 boost库和C++11中的智能指针以 ...

  2. 智能指针之shared_ptr基本概述

    1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象. 2.类似于vector,智能指针也是模板.创建智能指针: shared_ptr<string> ...

  3. 【C++11新特性】 C++11智能指针之shared_ptr

    C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...

  4. C++智能指针之shared_ptr与右值引用(详细)

    1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...

  5. 【STL学习】智能指针之shared_ptr

    前面已经学习过auto_ptr,这里补充另外一种智能指针,比auto_ptr要更强力更通用的shared_ptr. shared_ptr 简介及使用选择  几乎所有的程序都需要某种形式的引用计数智能指 ...

  6. C++智能指针: auto_ptr, shared_ptr, unique_ptr, weak_ptr

    本文参考C++智能指针简单剖析 内存泄露 我们知道一个对象(变量)的生命周期结束的时候, 会自动释放掉其占用的内存(例如局部变量在包含它的第一个括号结束的时候自动释放掉内存) int main () ...

  7. [5] 智能指针boost::shared_ptr

    [1]boost::shared_ptr简介 boost::shared_ptr属于boost库,定义在namespace boost中,包含头文件#include<boost/shared_p ...

  8. 关于智能指针boost::shared_ptr

    boost库中的智能指针shared_ptr, 功能强大, 且开销小,故受到广大coder的欢迎. 但在实际的使用过程中,笔者也发现了一些不足. 1.定制的删除器 shared_ptr除了可以使用默认 ...

  9. 智能指针(二):shared_ptr实现原理

    前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针 ...

随机推荐

  1. turtle学习笔记

    1.turtle的绘图窗体 turtle.setup(width, height, startx,starty) - setup()设置窗体大小及位置- 4个参数中后两个可选(后两个省略时默认窗口在屏 ...

  2. cmdb简介

    目录: 1.为啥要做cmdb

  3. WSL下卸载了zsh / fish后无法启动bash解决方案

    最近在鼓捣wsl,感觉自己用还是蛮好用的.听说1903要更新新的cmd,还蛮期待的 解决步骤: 建议先下载个everything , windows下非常好用的文件查找软件. 启动后搜索.bashrc ...

  4. [bfs,深度记录] East Central North America Regional Contest 2016 (ECNA 2016) D Lost in Translation

    Problem D Lost in Translation The word is out that you’ve just finished writing a book entitled How ...

  5. 常见排序算法总结分析之选择排序与归并排序-C#实现

    本篇文章对选择排序中的简单选择排序与堆排序,以及常用的归并排序做一个总结分析. 常见排序算法总结分析之交换排序与插入排序-C#实现是排序算法总结系列的首篇文章,包含了一些概念的介绍以及交换排序(冒泡与 ...

  6. Oracle数据库的创建表全

    CREATE TABLE "库名"."表名" ( "FEE_ID" VARCHAR2(10 BYTE) constraint ABS_FEE ...

  7. PHP7内核(一):发展史

    PHP1 1994年,一位名叫Rasmus lerdorf的兄台为了在网上展示自己的履历和网页流量的统计,用Perl开发了一套脚本,后来因与日俱增的需求无法得到满足,lerdorf便使用c语言进行了重 ...

  8. Mayor's posters POJ - 2528 线段树(离散化处理大数?)

    题意:输入t组数据,输入n代表有n块广告牌,按照顺序贴上去,输入左边和右边到达的地方,问贴完以后还有多少块广告牌可以看到(因为有的被完全覆盖了). 思路:很明显就是线段树更改区间,不过这个区间的跨度有 ...

  9. ClickHouse学习系列之一【安装说明】

    背景 最近花了些时间看了下ClickHouse文档,发现它在OLAP方面表现很优异,而且相对也比较轻量和简单,所以准备入门了解下该数据库系统.按照习惯第一步先安装,本文对其用户权限管理方面进行梳理说明 ...

  10. Redis调用lua生成验证码

    场景: ​ 通过微信公众号拿验证码在APP上绑定,为了防止重复,尝试使用reids-lua的方法实现此功能 以下是 php 调用 redis.eval 方法传入的 lua 方法,当然这只是修改后的,保 ...