C++智能指针的简单实现

news/2025/2/14 8:15:49/

文章目录

      • 1. 简述
      • 2. 简单实现
        • 2.1 整形的智能指针
        • 2.2 二叉树节点类型的智能指针
        • 2.3 通用指针类型
        • 2.4 unique_ptr
        • 2.5 引用计数 shared_ptr
      • 3. 存在问题
      • 4. Ref

1. 简述

智能指针即使用跟普通指针一样,
但是拥有自动回收内存的能力。

2. 简单实现

利用C++中的局部对象的构造析构特性,实现RAII。

2.1 整形的智能指针

简单的int类型的智能指针实现

class smp
{
public:explicit smp(int  *q = nullptr):p(q){}~smp(){delete p;}
private:int *p;
};
// ... smp sp(new int(10));*sp = 5;std::cout << *sp << std::endl;
2.2 二叉树节点类型的智能指针

还需要重载->符号,访问数据中的其他成员。

struct node {explicit node(int v = 3):left(nullptr),right(nullptr){}struct node *left;struct node *right;int value;
};
class node_smp {
public:explicit node_smp(node *q = nullptr):p(q){}~node_smp(){delete p;}node& operator*(){ return *p;}node* operator->(){ return p;}
public:node *p;
};node_smp nsmp(new node(10));nsmp->value = 20;std::cout << nsmp->value << std::endl;
2.3 通用指针类型
template<typename T>
class smart_ptr {
public:explicit smart_ptr(T *p = nullptr):q(p){}~smart_ptr(){delete q;q = nullptr;}T& operator *(){ return *q;}T* operator->(){return q;}private:T *q;
};smart_ptr<node> smp(new node(10));smp->value = 100;std::cout << smp->value << std::endl;
2.4 unique_ptr

在上面代码的基础上禁止资源的转移,就是unique_ptr的雏形啦。

template<typename T>
class unique_ptr_ {
public:explicit unique_ptr_(T *p = nullptr):ptr(p){}~unique_ptr_(){delete ptr;}unique_ptr_(const unique_ptr_& p) = delete;unique_ptr_& operator=(const unique_ptr_& p) = delete;
private:T *ptr;
};
2.5 引用计数 shared_ptr

到目前为止,实际上我们并没有处理拷贝构造函数和赋值函数。
在一个返回内的智能指针,且不会在别的地方被引用。
也就是该智能指针无法在另外一个地方再使用。

那么怎么实现能使用多个智能指针对象呢,标准库实现的方式是引用计数。
而要对多个对象进行计数,且多个对象的销毁并不确定,所以只能在对象首次使用时使用在堆上的分配一个内存进行引用计数。

当最后一个只能对象销毁时,销毁资源。

template<typename  T>
class shared_ptr_ {
public:explicit shared_ptr_(T *data = nullptr):RefCnt(new int {0}) {data_ = data;*RefCnt = 0;if (data_) {++*RefCnt;}}~shared_ptr_() {--*RefCnt;if (*RefCnt == 0) {delete data_;delete RefCnt;}}shared_ptr_& operator=(const shared_ptr_ & p) {if ( *this != p) {RefCnt = p.RefCnt;data_ = p.data_;++*RefCnt;}return *this;}shared_ptr_(const shared_ptr_ &p) {data_ = p.data_;RefCnt = p.RefCnt;++*RefCnt;}T& operator*(){return *data_;}T* operator->(){return data_;}
private:T *data_;int *RefCnt;
};

在使用循环链表的过程中即存在这种情况:

template<typename  T>
class shared_ptr_ {
public:explicit shared_ptr_(T *data = nullptr):data_(data),RefCnt(new int {0}){if (data_) {++*RefCnt;}}~shared_ptr_() {if (*RefCnt) {--*RefCnt;if ( *RefCnt )std::cout << "current ref: "<< *RefCnt << std::endl;}if (*RefCnt == 0) {delete data_;delete RefCnt;}}shared_ptr_<T>& operator=(const shared_ptr_<T> & p)  {if ( this != &p) {RefCnt = p.RefCnt;data_ = p.data_;if (*RefCnt) {++*RefCnt;}}return *this;}shared_ptr_(const shared_ptr_ &p) {data_ = p.data_;RefCnt = p.RefCnt;if (*RefCnt)++*RefCnt;}T& operator*(){return *data_;}T* operator->(){return data_;}
private:T *data_;int *RefCnt;
};class List {
public:explicit List(int _v = 0):v(_v), pPre(), pNext(){}~List(){std::cout << "delete List " << v << std::endl;}int v;shared_ptr_<List> pPre;shared_ptr_<List> pNext;
};int main()
{shared_ptr_<List> p1(new List(2));shared_ptr_<List> p2(new List(3));p1->pPre = p2;p2->pPre = p1;p1->pNext = p2;p2->pNext = p1;return 0;
}

输出

current ref: 2
current ref: 2

由于实际上在链表中,并不实际占有资源而只是一个引用。所以会出现程序运行后还剩两个计数。
即对于p1,还有p1->pPrep1->next两个指针计数。

3. 存在问题

更好的实现就要看boost和标准库这些的相关实现了。

  • 循环引用未解决
  • 线程安全问题
  • 异常安全
  • 继承

4. Ref

code_review
csdn
code_project


http://www.ppmy.cn/news/1223559.html

相关文章

Python开源项目GPEN——人脸重建(Face Restoration),模糊清晰、划痕修复及黑白上色的实践

无论是自己、家人或是朋友、客户的照片&#xff0c;免不了有些是黑白的、被污损的、模糊的&#xff0c;总想着修复一下。作为一个程序员 或者 程序员的家属&#xff0c;当然都有责任满足他们的需求、实现他们的想法。除了这个&#xff0c;学习了本文的成果&#xff0c;或许你还…

PyTorch深度学习原理与实现

PyTorch深度学习原理与实现 1. 引言 深度学习发展历程 感知机网络&#xff08;解决线性可分问题&#xff0c;20世纪40年代&#xff09; BP神经网络&#xff08;解决线性不可分问题&#xff0c;20世纪80年代&#xff09; 深度神经网络&#xff08;海量图片分类&#xff0c;2…

珠宝饰品展示预约小程序的效果如何

金银珠宝翡翠行业几乎每个人都会接触&#xff0c;比如黄金小手饰&#xff0c;翡翠小挂件等&#xff0c;当然除了购买外&#xff0c;还有附加服务&#xff0c;如珠宝鉴定、定制等&#xff0c;同时这个行业具有较强的到店属性&#xff0c;除了价值较小的配件外&#xff0c;真金白…

【漏洞复现】用友U8-Cloud 存在任意文件上传漏洞

漏洞描述 U8 cloud 聚焦成长型、创新型企业的云 ERP,基于全新的企业互联网应用设计理念,为企业提供集人财物客、产供销于一体的云 ERP 整体解决方案,全面支持多组织业务协同、智能财务,人力服务、构建产业链智造平台,融合用友云服务实现企业互联网资源连接、共享、协同。…

Golang抓包:实现网络数据包捕获与分析

介绍 在网络通信中&#xff0c;网络数据包是信息传递的基本单位。抓包是一种监控和分析网络流量的方法&#xff0c;用于获取网络数据包并对其进行分析。在Golang中&#xff0c;我们可以借助现有的库来实现抓包功能&#xff0c;进一步对网络数据进行分析和处理。 本文将介绍如…

ES6 导入导出

ES6 导入导出 ES6引入了原生的模块化支持&#xff0c;使得JavaScript代码可以被划分为可重用的模块。这些模块可以导出部分代码&#xff08;如函数、对象、类等&#xff09;&#xff0c;并被其他模块导入使用。 export 命名导出&#xff08;Named Exports&#xff09; 可以从…

java接收前端easyui datagrid传递的数组参数

这篇文章分享一下怎么在easyui的datagrid刷新表格时&#xff0c;在后端java代码中接收datagrid传递的数组参数。 数组来源于技能的tagbox&#xff08;标签框&#xff09;&#xff0c;tagbox和combobox的区别是tagbox可以选择多项。 标签框渲染的代码为 $("#skill_ids"…

怎样班群发成绩?

身为老师&#xff0c;定期发布学生成绩是项重要任务。在过去&#xff0c;这项任务需要手动操作&#xff0c;工作量大而且总是发错。不过诶&#xff0c;现在我们可以通过各种方式实现学生自助查询成绩&#xff0c;既提高了效率又不会发错&#xff01; 就是需要制作一个查询系统。…