目录

1 shared_ptr的实现原理

2 代码简单实现

参考


1 shared_ptr的实现原理

智能指针的一种通用实现技术是使用引用计数。智能指针类将一个计数器与智能指针指向的对象相关联,用来记录有多少个智能指针指向相同的对象,并在恰当的时候释放对象。

每次创建类的新对象时初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,引用计数加1;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

由图中可以看到,实际上引用计数、自定义销毁等都不是直接存储在shared_ptr中,而是通过一个指针指向的一个控制块存储的,控制块是动态分配的内存 。

2 代码简单实现

#include <iostream>
#include <memory>
#include <string>
#include <assert.h>using namespace std;// 使用一个类来管理引用计数
class RefCounter {
public:RefCounter(long val) : count(val) {};void add_ref() { // c++标准库中的操作是一个原子操作,且要保证线程安全(如加锁操作)++count;}const long reduce_ref() {return --count;}long get_use_count() const noexcept {return count;}
private:long count;
};// 自定义一个模板类的智能指针
template<typename Element_Type>
class SmartPointer {
public:// 使用一般指针类型,初始化一个智能指针SmartPointer(Element_Type* ptr = nullptr) : mp(ptr) {if (mp) {mCount = new RefCounter(1);}else {mCount = new RefCounter(0);}}// 拷贝构造函数,使用一个已有的智能指针,初始化一个新的智能指针// 新的智能指针拥有了原来的智能指针管理的指针地址 和 引用计数数值,同时,新的智能指针引用计数加1(当然,原来的指针智能指针引用计数不会发生变化)SmartPointer(const SmartPointer& ptr) {mp = ptr.mp;mCount = ptr.mCount;mCount->add_ref();}// 赋值函数:当前智能指针引用计数减1,若减到0就销毁原来指向的内存。// 举例: sp2 = sp3// 否则使用新的智能指针sp3 的属性覆盖当前智能指针sp2 的属性,并使引用计数加1// (加的既是 当前智能指针sp2 的引用计数, 同时又是新的智能指针sp3的引用计数, 因为它们的引用计数是同一地址对应的变量 count)SmartPointer& operator=(const SmartPointer& ptr) {if (mp == ptr.mp) {return *this;}if (mp) {if (mCount->reduce_ref() == 0) {delete mp;delete mCount;}}mp = ptr.mp; //因为使用引用计数,所以直接用一个指针的值覆盖另一个指针的值,只要引用计数不减到0就先不必销毁原有的内存,也不必担心内存会泄漏(地址未归还系统)mCount = ptr.mCount; // (加的既是 当前智能指针sp2 的引用计数, 同时又是新的智能指针sp3的引用计数, 因为它们的引用计数是同一地址对应的变量 count)mCount->add_ref();return *this;}// 解引用 dereference // 返回原始指针指向的变量(实例)的引用Element_Type& operator*() {assert(mp != nullptr);return *mp;}Element_Type* operator->() {assert(mp != nullptr);return mp;}operator bool() const {return mp;}// 每析构一次智能指针就减少一次引用计数~SmartPointer() {if (mCount->reduce_ref() == 0) {delete mp;delete mCount;}}size_t use_count() {return mCount->get_use_count();}
private:Element_Type* mp;RefCounter*   mCount;
};// 简单定义一个使用智能指针管理内存的用户类
class Person {
public:Person(int age, string name) : mAge(age), mName(name) {};string info() {string info = "Name: " + mName + ", Age:" + std::to_string(mAge);return info;}
private:int mAge;string mName;
};int main() {SmartPointer<Person> sp1(new Person(10, "zhangsan"));SmartPointer<Person> sp2(sp1); // 使用智能指针拷贝构造一个新的智能指针,则 sp2 sp3 引用计数都+1SmartPointer<Person> sp3(new Person(20, "Lisi"));std::cout << sp1.use_count() << ", " << sp1->info() << std::endl; // 2, Name: zhangsan, Age:10std::cout << sp2.use_count() << ", " << sp2->info() << std::endl; // 2, Name: zhangsan, Age:10std::cout << sp3.use_count() << ", " << sp3->info() << std::endl; // 1, Name: Lisi, Age:20sp2 = sp3;  // 使用智能赋值一个智能指针,被赋值的智能sp2原来对应的指针的引用计数-1,用于赋值的智能指针引用计数+1std::cout << sp1.use_count() << ", " << sp1->info() << std::endl; // 1, Name: zhangsan, Age:10std::cout << sp2.use_count() << ", " << sp2->info() << std::endl; // 2, Name: Lisi, Age:20std::cout << sp3.use_count() << ", " << sp3->info() << std::endl; // 2, Name: Lisi, Age:20return 0;
}// 将上述main函数中 SmartPointer 改成 shared_ptr std::cout输出的结果是一样的。 

参考

C++11--智能指针详解及实现

用c++简单实现智能指针

如何实现一个简单的智能指针

C++_实现一个简单的智能指针shared_ptr相关推荐

  1. boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选

    作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...

  2. get方法报空指针_智能指针shared_ptr踩坑笔记

    平时写代码一直避免使用指针,但在某些场景下指针的使用还是有必要的.最近在项目中简单使用了一下智能指针(shared_ptr),结果踩了不少坑,差点就爬不出来了.痛定思痛抱着<Cpp Primer ...

  3. Android——一个简单的智能家居系统

    一个简单的智能家居系统 效果展示 启动应用界面 登陆界面 导航界面 温度界面 湿度界面 烟雾传感器界面 人体红外传感器界面 效果展示 以下为整个程序的操作流程,因为CSDN不能上传太大文件,所以画质比 ...

  4. 动手做一个简单的智能小车

    动手做一个简单的智能小车 来到CNDN一年了,看到了许多大佬的杰出作品.也该写点什么来回馈给大家了前不久接触了单片机,想提前进行实践一下所以有想法做一个实体出来,想来想去难的怕自己搞不定,但是还好找到 ...

  5. 一个简单的智能停车APP——抽屉式侧边栏

    一个简单的智能停车APP 功能介绍 代码详解 总结 功能介绍 先展示效果图: 侧边栏由MaterialDesign(原质化设计)框架设计而成. 由DrawerLayout+NavigationView ...

  6. 使用 Python 实现一个简单的智能聊天机器人

    使用 Python 实现一个简单的智能聊天机器人 文章目录 使用 Python 实现一个简单的智能聊天机器人 简要说明 总体的思路 需要准备的环境 接收用户的语音输入, 并将其存为音频文件 调用百度A ...

  7. 智能指针shared_ptr的几个例子

    #include <string> #include <iostream> #include <memory> //智能指针定义在头文件memory中,例如shar ...

  8. 智能指针 shared_ptr 解析

    近期正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦.写篇blog整理一下. LinJM   @HQU s ...

  9. 智能指针shared_ptr的原理、用法和注意事项

    智能指针shared_ptr的原理.用法和注意事项 1 前言 2 shared_ptr原理 3 shared_ptr的基本用法 3.1 初始化 3.2 获取原始指针 4 智能指针和动态数组 4.1 c ...

  10. 智能指针shared_ptr的用法

    智能指针shared_ptr的用法 2016-12-03 15:39 by jiayayao, 360 阅读, 0 评论, 收藏, 编辑 为了解决C++内存泄漏的问题,C++11引入了智能指针(Sma ...

最新文章

  1. 面试题6:用两个栈实现队列
  2. 阻抗匹配工具_工具 | 9R Fret Polishing Wheels 品丝抛光轮
  3. 用C#访问Hotmail -转
  4. Git 使用篇一:初步使用GitHub,下载安装git,并上传项目
  5. GridView绑定数据源 绑定DataReader /DataSet /DataTable
  6. spark-submit的使用
  7. 浏览器屏蔽flash视频广告
  8. openstreetmap_OpenStreetMap成立10周年,开源医疗设备等等
  9. 在web开发中,为什么前端比后端更得到转行程序员的青睐?必看
  10. php在客户端禁用cookie时让session不失效的解决方法
  11. 课堂考试作弊检测系统,情绪识别、表情识别和人脸识别结合
  12. Flutter之RenderObjectWidget
  13. C# try-catch-finally 语句异常的类型
  14. 字符串解码DecodeString
  15. java IEnumerator_获取实现接口的所有类型
  16. Java 高并发编程详解:多线程与架构设计
  17. 魔兽8.0最新服务器人口普查,魔兽世界8.2最新人口普查 2019各服务器人口普查信息汇总...
  18. HTTP协议报文头部结构和Web相关工具
  19. python add sheet_Python系列(6)——使用openpyxl将三种类型的数据添加进新sheet及已有的sheet中且不覆盖原数据...
  20. JEPG图像存储结构

热门文章

  1. linux硬件 软件raid,linux学习之路之磁盘阵列RAID及硬件RAID和软件RAID的区别
  2. centos java进程号_centos中分析java占用大量CPU资源的原因
  3. 2018.11.22 mac中允许所有安装来源的命令 Mac窗口标题显示文件的路径
  4. eslint配置文件解析
  5. selenium.common.exceptions.WebDriverException: Message: Failed to start browser:搞哭了
  6. ECCV 2016 paper list
  7. Hadoop 参数配置优化
  8. 分类数据转换为树形结构
  9. Yii 2.0 权威指南(7) 关键概念
  10. Linux服务器异常关机,重启启动后weblogic无法启动