文章目录

  • unique_ptr 智能指针的实现
  • shared_ptr 智能指针的实现
  • 指针类型转换

unique_ptr 智能指针的实现

一个对象只能被单个unique_ptr 所拥有。

#include <iostream>using namespace std;/*增加模板类型,保证智能指针的类型是由传入的类型决定的*/
template <typename T>class smart_ptr {public:explicit smart_ptr(T *ptr = nullptr): ptr_(ptr){}/*移动构造函数,当前智能指针仅能被一个对象引用*/smart_ptr(smart_ptr&& other) {ptr_ = other.release();}/*如果我们想要消除移动构造和拷贝构造,只需要将其 构造标记为delete*///smart_ptr(const smart_ptr&) = delete;//smart_ptr& operator=(const smart_ptr&) = delete;/*在构造参数时直接生成新的智能指针,从而不再需要在函数体中构造临时对象,当前支持移动构造进行函数对象的构造。*/smart_ptr& operator=(smart_ptr rhs) {rhs.swap(*this);return *this;}  T* release() {T* ptr = ptr_;ptr_ = nullptr;return ptr;}void swap(smart_ptr& rhs) {using std::swap;//标准模板库的交换函数swap(rhs.ptr_,ptr_);}~smart_ptr(){delete ptr_;}T* get() const{ return ptr_;}/*指针的特性,可以通过*解引用访问 */T& operator*() const{return *ptr_;}/*指针的特性,可以通过-> 访问指针的地址内容*/T* operator->() const{return ptr_;}/*重载bool运算符,能够让smart_ptr像指针一样用在布尔表达式中*/operator bool() const{return ptr_;}private:T* ptr_;
};class Shape{public:virtual void create_shape() = 0;virtual ~Shape(){}
};class Circle: public Shape{public:Circle(){cout << "Circle::Circle()" << endl;}void create_shape(){cout << "create shape: Circle" << endl;}~Circle(){cout << "Circle::delete()" << endl;}
};class Triangle: public Shape{public:Triangle(){cout << "Triangle::Tirangle()" << endl;}void create_shape(){cout << "create shape: Triangle" << endl;}~Triangle(){cout << "Triangle::delete()" << endl;}
};int main()
{smart_ptr<Shape> ptr1(new Circle);smart_ptr<Shape> ptr2(nullptr);smart_ptr<Shape> ptr3 ;//ptr3 = ptr1; //编译报错,赋值需要一个对象(而非引用),因而进入执行之前需要引发一个构造,但是此时没有可用的构造函数ptr3 = std::move(ptr2); // 编译正常,支持移动构造 return 0;
}

shared_ptr 智能指针的实现

多个shared_ptr可以共享同一个对象,当他们全部失效的时候,这个对象才会被删除。

此时对shared_ptr的需求是共享 同一个对象时也需要共享同一个计数,当最后一个指向对象(和共享计数)的shared_ptr析构时,它需要删除对象和共享计数。

在以上unique_ptr的实现基础上增加引用计数相关的操作,实现如下:

#include <iostream>using namespace std;/*增加一个引用计数类,来记录当前对象被智能指针引用的次数*/
class shared_count{public:shared_count():count_(1) {}void add_count(){++count_;}long reduce_count(){return --count_;}long get_count() {return count_;}
private:long count_;
};/*增加类模板,保证智能指针的类型是由传入的类型决定的*/
template <typename T>class smart_ptr {public:explicit smart_ptr(T *ptr = nullptr): ptr_(ptr){if(ptr) {shared_count_ = new shared_count();}}/*移动构造函数,当前智能指针仅能被一个对象引用,同时不进行引用计数的自加*/template <typename U>smart_ptr(smart_ptr<U>&& other) {ptr_ = other.release();if(ptr_) {shared_count_ = other.shared_count_;other.ptr_ = nullptr;}}/*拷贝构造函数,支持子类对象向父类对象的拷贝*/template <typename U>smart_ptr(const smart_ptr<U>& other) {ptr_ = other.ptr_;if(ptr_) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}}/*同类型对象的拷贝构造函数*/smart_ptr(smart_ptr & other) {ptr_ = other.ptr_;if(ptr_) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}}/*在构造参数时直接生成新的智能指针,从而不再需要在函数体中构造临时对象,当前支持移动构造进行函数对象的构造。*/smart_ptr& operator=(smart_ptr rhs) {rhs.swap(*this);return *this;} T* release() {T* ptr = ptr_;ptr_ = nullptr;return ptr;}void swap(smart_ptr& rhs) {using std::swap;swap(rhs.ptr_,ptr_);swap(rhs.shared_count_,shared_count_);}long use_count() const {if(ptr_) {return shared_count_->get_count();} else {return 0;}}~smart_ptr(){//    cout << "smart_ptr::delete count is " << shared_count_ -> get_count() << endl;if(ptr_ && !shared_count_ -> reduce_count()){delete ptr_;delete shared_count_;}}T* get() const{ return ptr_;}T& operator*() const{return *ptr_;}T* operator->() const{return ptr_;}operator bool() const{return ptr_;}private:T* ptr_;shared_count* shared_count_;//统计对象引用计数的类
};class Shape{public:virtual void create_shape() = 0;virtual ~Shape(){}
};class Circle: public Shape{public:Circle(){cout << "Circle::Circle()" << endl;}void create_shape(){cout << "create shape: Circle" << endl;}~Circle(){cout << "Circle::delete()" << endl;}
};class Triangle: public Shape{public:Triangle(){cout << "Triangle::Tirangle()" << endl;}void create_shape(){cout << "create shape: Triangle" << endl;}~Triangle(){cout << "Triangle::delete()" << endl;}
};int main()
{smart_ptr<Shape> ptr1(new Circle);cout << "use count of ptr1 is: " << ptr1.use_count() << endl;smart_ptr<Shape> ptr2;cout << "use count of ptr2 was: " << ptr2.use_count() << endl;//ptr2 = std::move(ptr1); // 移动拷贝构造,不进行计数增加(可查看以上的实现)ptr2 = ptr1; //普通的拷贝构造,支持多个指针共享同一个对象,则对应智能指针的共享计数增加cout << "use count of ptr2 is now: " << ptr2.use_count() << endl;if(ptr1) {cout << "ptr1 is not empty " << endl; }return 0;
}

输出如下:

Circle::Circle()
use count of ptr1 is: 1
use count of ptr2 was: 0
use count of ptr2 is now: 2
Circle::delete()

指针类型转换

C++已有的强制类型转换有如下几种:

  • static_cast 用于类层次结构中基类和派生类之间指针或引用的转换
  • reinterpret_cast 改变指针或引用的类型、将指针或引用转换为一个足够长度的整形、将整型转换为指针或引用类型
  • const_cast 用于强制去掉不能被修改的常数特性
  • dynamic_cast dynamic_cast是运行时处理的,运行时要进行类型检查。

智能指针需要实现类似的函数模板,想要达到以上对应的强制类型转换的功能,我们需要增加构造函数,且允许在对智能指针内部的指针对象赋值时,使用一个现有的智能指针的共享计数。如下所示:

template <typename U>
smart_ptr(const smart_ptr<U> &other, T* ptr) { //拷贝构造时,使用T* ptr进行类型转换_ptr = ptr;if(_ptr) {other.shared_count_ -> add_count();shared_count_ = other.shared_count_;}
}

根据以上代码,实现dynamic_pointer_cast

template <typename T, typename U>
smart_ptr <T> dynamic_pointer_cast(const smart_ptr<U> &other) {T *ptr = dynamic_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}

使用方式如下:

smart_ptr<Circle> ptr3 = dynamic_pointer_cast<Circle> ptr2;

同理实现其他三个 强制类型转换的逻辑实现如下:

template <typename T, typename U>
smart_ptr <T> static_pointer_cast(const smart_ptr<U> &other) {T *ptr = static_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}template <typename T, typename U>
smart_ptr <T> reinterpret_pointer_cast(const smart_ptr<U> &other) {T *ptr = reinterpret_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}template <typename T, typename U>
smart_ptr <T> const_pointer_cast(const smart_ptr<U> &other) {T *ptr = const_cast<T*> (other.get());return smart_ptr<T> (other,ptr);
}

C++ 智能指针(unique_ptr / shared_ptr)代码实现相关推荐

  1. C++ 实现智能指针:shared_ptr 和 unique_ptr

    简 述: C++11 智能指针的深入分析,和动手实现简版的智能指针 std::shared_ptr .std::unique_ptr 文章目录 背景 std::shared_ptr 原理 代码 ref ...

  2. C++11中的智能指针unique_ptr、shared_ptr和weak_ptr详解

    目录 1.引言 2.什么是智能指针? 3.在Visual Studio中查看智能指针的源码实现 4.独占式指针unique_ptr 4.1.查看unique_ptr的源码实现片段 4.2.为什么uni ...

  3. C++智能指针unique_ptr与shared_ptr

    文章目录 1.unique_ptr特点 2.unique_ptr例子 3.unique_ptr总结 4.shared_ptr特点 5.shared_ptr例子 6.shared_ptr中的自定义删除器 ...

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

    http://blog.csdn.net/Xiejingfa/article/details/50750037 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...

  5. C++智能指针之shared_ptr

    C++智能指针之shared_ptr 前言 一.Shared_ptr 1.1 shared_ptr类的操作 1.2 make_shared函数 1.3 shared_ptr的拷贝赋值 1.4 shar ...

  6. 智能指针用法及其代码详解

    网络上大多有关智能指针的解析只停留于简单的字面理解,今天来详细解析一下三种智能指针的用法以及具体的代码. 目录 概念 RAII机制介绍 智能指针雏形 shared_ptr原理介绍 shared_ptr ...

  7. C++11 智能指针之shared_ptr

    0.Overview 在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如: 有些内存资源已经被释 ...

  8. 【C++11智能指针】shared_ptr的初始化、拷贝构造和拷贝赋值、移动构造和移动赋值

    文章目录 1.智能指针概述 2.shared_ptr的初始化 2.1 shared_ptr和new结合使用(直接初始化) 2.2 make_shared函数 3.shared_ptr的拷贝构造和拷贝赋 ...

  9. C++ 智能指针std::shared_ptr简单使用和理解

    参考:https://blog.csdn.net/u011068702/article/details/83692838 1  智能指针std::shared_ptr相关知识和如何使用 我们这里先说下 ...

最新文章

  1. 2022-2028年中国侧线油行业市场研究及前瞻分析报告
  2. 使用Leangoo管理产品Backlog
  3. Android Support v4、v7、v13的区别和应用场景
  4. JDK8对并发的新支持
  5. css不换行属性_前端 | css display:flex 的六个属性你知道吗
  6. 轮廓的查找、表达、绘制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)
  7. matlab平稳随机过程的功率谱密度,平稳随机过程的功率谱密度
  8. 南京农业大学计算机组成原理,2017年南京农业大学信息科学技术学院853计算机专业基础综合之计算机组成原理考研强化模拟题...
  9. 《Linux编程》课堂测验 ·002【Shell编程】
  10. sift算法的主要步骤
  11. java join字符串_Java字符串join()
  12. UE4更改天空盒材质
  13. 如何手动释放Python的内存
  14. CARLA 笔记(07)— 地图和导航(Landmarks、Waypoints、Lanes、Junctions、Environment Objects、路径点导航、地图导航、分层和非分层地图)
  15. 数学建模拿到赛题后怎么办及一些(“歪门邪道”)小技巧——赛前必看
  16. 手机APP测试(三)
  17. CDH6.3.1监控界面Hive修改参数
  18. linux模拟手机号码,虚拟手机号码接收短信
  19. [BZOJ4327] JSOI2012玄武密码
  20. linux echo 字体大小 背景 字体颜色 的编码

热门文章

  1. Elasticsearch内存分配设置详解
  2. 《OpenCV3编程入门》学习笔记6 图像处理(六)图像金字塔与图片尺寸缩放
  3. Winograd,GEMM算法综述(CNN中高效卷积实现)(下)
  4. latex 公式不居中_LaTex小技巧,祝你论文一臂之力!
  5. access update语句执行_MySQL 中 update 修改数据与原数据相同会再次执行吗?
  6. 站覆盖范围_你了解无线覆盖范围和穿墙能力吗?别再走进这些误区了
  7. java命名course为名的class_Java教程之变量命名
  8. C语言随机字母生成,C++ 随机数字以及随机数字加字母生成的案例
  9. 前后端分离的接口规范是什么?
  10. GitHub开源:17M超轻量级中文OCR模型、支持NCNN推理