【C++数据结构】智能指针的构建

news2025/1/16 15:05:57

文章目录

  • 一、构建智能指针的原因
  • 二、智能指针分析
  • 三、实现智能指针
    • 数据结构使用的编译器
      • 创建Qt控制台项目
    • 智能指针的构建
      • 新文件结构
      • 创建指针成员
      • 实现析构函数
      • 构造函数
      • 操作符重载
      • 成员函数的实现
      • 拷贝构造函数和"="重载操作符
  • 四、代码一览
  • 总结


一、构建智能指针的原因

众所周知,C++是没有垃圾回收的,就会导致以下问题:
1、导致动态申请堆空间,用完后不归还
2、会导致程序的内存泄露,进而影响整个程序,甚至可能是整个电脑
3、指针无法控制所指堆空间的生命周期

我们就需要设计一个类SmartPointer他的功能如下:

  • 指针生命周期结束时主动释放堆空间
  • 一片堆空间最多由一个指针标识
    原因:因为我们要在析构函数中释放堆空间,如果2个智能指向同一片空间,就会导致他被释放2次,就会得到意想不到的结果!!!
  • 杜绝指针运算和指针比较。

二、智能指针分析

  1. 通过类模板描述指针的行为。
    在之前的第一节课我们已经讲过了,可以使用类模板来加强我们的数据结构的复用,在这里我们也是使用类模板来定义我们的SmartPointer使他能够定义不同类型的指针对象

  2. 重载指针特征操作符(->*)。
    利用对象模拟原生指针的行为

三、实现智能指针

数据结构使用的编译器

我使用的编译器是Qt5.9.4,操作系统环境为Ubuntu 22,如果大家使用的是vs/qt(其他版本),或是其他操作系统,我都会讲他们函数的不同地方,例如函数名称的不同!!!

创建Qt控制台项目

1、在侧边栏打开qt creator
在这里插入图片描述
如果在侧边栏未找到怎么办?
那就进行下列操作:
在这里插入图片描述在侧边栏找到点的按钮,点击他。
在这里插入图片描述
在上方搜索qt,下面的这个应用就是qt,点击打开他。

2、创建新的项目
在这里插入图片描述
进入之后点击New Project

在这里插入图片描述
之后选择第二个。
之后一路Choose即可,注意在此步的下一步是选择路径的,路径不能有中文

进入之后就是这样的:
在这里插入图片描述

智能指针的构建

点击我们的项目,创建新的文件:
在这里插入图片描述
在这里插入图片描述
选择C++ Header File,因为我们要使用模板技术,所以只需要头文件即可。具体的原因如下:
使用C++模板技术时,只需要创建头文件的原因是因为模板是一种在**编译时生成代码的机制**。在C++中,模板可以用来定义通用的数据结构和算法,以适应不同类型的数据
当我们编写一个模板类或者模板函数时,我们只需要把模板的声明和定义写在头文件中即可。这是因为模板的实例化是在编译时完成的,而不是链接或运行时。当程序在编译时遇到模板的使用,编译器会根据实际使用的类型生成对应的代码。
由于模板的代码是泛化的,可以适用于不同的类型,在编译时需要进行模板的实例化。如果把模板定义分离到实现文件中,编译器无法在编译时生成相应的实例化代码,导致链接时出现编译错误。
因此,为了正确使用C++模板技术,我们通常将模板的声明和定义都写在头文件中。这样,在包含头文件时,编译器可以看到模板的定义,并根据需要生成相应的实例化代码,保证程序的正确性。
需要注意的是,模板的成员函数的定义通常也需要放在头文件中,以便在实例化时能够正确地内联函数。如果将模板的定义和实现都放在头文件中,会使代码更易于 维护和理解,并且避免了编译和链接时的错误。


在我们本数据结构,我们都会使用一个叫做命名空间来包含我们的数据结构类
他的语法格式如下:

namespace MYLib
{
	//someclass
	class Myclass
	{
		
	};
	//someFunction
	void func()
	{
		
	}
}

我们在使用他的时候就需要uising namespace MYLib和添加对应的头文件,才可以使用类,要不然需要像这样MYLib::func()来使用

新文件结构

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

namespace MyStruct
{
    //your class
}

#endif // SMARTPOINTER_H

创建指针成员

我们在类中需要使用原生指针。并且我们还需要使用泛指类型

	template<typename T>
    class SmartPointer
    {
    protected:
        T *m_pointer;
    public:
        
    };

实现析构函数

在我们智能指针中,最重要的就是自动释放指针,所以我们要使用析构函数来帮我们释放指针。

~SmartPointer()
{
    delete m_pointer;
}

构造函数

只需要把m_pointer指向参数即可,参数需要默认参数提法灵活度

SmartPointer(T*point = nullptr)
{
    m_pointer = point;
}

操作符重载

*操作符分析

int *a = new int(10);
cout << *a << endl;

通过运行上面的程序,我们可以发现*他是一个取值操作符,所以我们重载他的时候需要返回一个具体的数,而不是指针
具体实现如下:

T& operator *()
{
     return *m_pointer;
}

->操作符分析:

T*operator ->()
{
    return m_pointer;
}

成员函数的实现

1、判断是否为空

bool isNull()
{
    return m_pointer == nullptr;
}

2、得到指针

T *get()
{
    return m_pointer;
}

拷贝构造函数和"="重载操作符

在这里插入图片描述
具体的过程如图所示

拷贝构造函数:

SmartPointer(const SmartPointer&obj)
{
    m_pointer = obj.m_pointer;//本类的指针指向obj里面的指针指向的东西
	
	/*使用const_cast消除const属性*/
    const_cast<SmartPointer<T>>(obj).m_pointer = nullptr;//把参数的m_pointer指向null
}

"="重载:
此处实现和上面差不多,无非是需要判断是否为自赋值
自赋值是什么:

int a = 10;
a = a;

像上面这种a =a;就属于自赋值,此时我们如果去做一遍赋值操作就会大大降低效率所以需要避免!!!

判断自赋值的方法如下:
通过比较地址即可知道是否为同一个类的自赋值

SmartPointer<T> &operator =(const SmartPointer&obj)
{
    if(&obj!=this)
    {
        m_pointer = obj.m_pointer;

        const_cast<SmartPointer<T>>(obj).m_pointer = nullptr;
    }
    
    return *this;//放回自身,加强连续赋值
}

四、代码一览

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

namespace MyStruct
{

    template<typename T>
    class SmartPointer
    {
    protected:
        T *m_pointer;
    public:
        SmartPointer(T*point = nullptr)
        {
            m_pointer = point;
        }

        SmartPointer(const SmartPointer&obj)
        {
            m_pointer = obj.m_pointer;

            const_cast<SmartPointer<T>>(obj).m_pointer = nullptr;
        }
        
        SmartPointer<T> &operator =(const SmartPointer&obj)
        {
            if(&obj!=this)
            {
                m_pointer = obj.m_pointer;
    
                const_cast<SmartPointer<T>>(obj).m_pointer = nullptr;
            }
            
            return *this;
        }

        T& operator *()
        {
            return *m_pointer;
        }

        T*operator ->()
        {
            return m_pointer;
        }

        bool isNull()
        {
            return m_pointer == nullptr;
        }

        T *get()
        {
            return m_pointer;
        }

        ~SmartPointer()
        {
            delete m_pointer;
        }
    };

}

#endif // SMARTPOINTER_H

总结

SmartPointer中,最重要的就是要实现析构函数的自动释放功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/896672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过 kk 创建 k8s 集群和 kubesphere

官方文档&#xff1a;多节点安装 确保从正确的区域下载 KubeKey export KKZONEcn下载 KubeKey curl -sfL https://get-kk.kubesphere.io | VERSIONv3.0.7 sh -为 kk 添加可执行权限&#xff1a; chmod x kk创建 config 文件 KubeSphere 版本&#xff1a;v3.3 支持的 Kuber…

中睿天下受邀参加第六届电力信息通信新技术大会并发表主题演讲

2023年8月9-11日&#xff0c;中国电力企业联合会科技开发服务中心以“加快数字化转型助力新型电力系统建设”为主题&#xff0c;在杭州举办2023年&#xff08;第六届&#xff09;电力信息通信新技术大会暨数字化发展论坛。 大会旨在加快推进“双碳”目标下的新型能源体系和新型…

【电商领域】Axure在线购物商城小程序原型图,品牌自营垂直电商APP原型

作品概况 页面数量&#xff1a;共 60 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;网上商城、品牌自营商城、商城模块插件 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本作品为品牌自营网上商城…

前端技术Vue学习笔记--004

Vue学习 文章目录 Vue学习一、scoped解决样式冲突二、data必须是一个函数三、组件通信3.1、组件关系3.2、组件通信解决方案3.3、父传子通信3.4、子传父通信3.5、组件通信案例 四、prop语法4.1、prop语法基础语法4.2、 <font color blue>prop校验4.3、prop&data、单向…

流程图用什么软件做?这几款常用软件了解一下

流程图用什么软件做&#xff1f;流程图是在工作中非常常见的一种图形&#xff0c;它可以清晰地展示一个流程的步骤和流向。在工作中&#xff0c;我们经常需要制作各种流程图&#xff0c;如项目流程图、销售流程图等&#xff0c;以便更好地组织和管理工作。那么&#xff0c;应该…

boot-admin整合flowable官方editor-app源码进行BPMN2-0建模

boot-admin整合flowable官方editor-app源码进行BPMN2-0建模&#xff08;续&#xff09;书接上回 项目源码仓库github项目源码仓库gitee boot-admin 是一款采用前后端分离模式、基于SpringCloud微服务架构的SaaS后台管理框架。系统内置基础管理、权限管理、运行管理、定义管理…

Spark第三课

1.分区规则 1.分区规则 shuffle 1.打乱顺序 2.重新组合 1.分区的规则 默认与MapReduce的规则一致,都是按照哈希值取余进行分配. 一个分区可以多个组,一个组的数据必须一个分区 2. 分组的分区导致数据倾斜怎么解决? 扩容 让分区变多修改分区规则 3.HashMap扩容为什么必须…

【源码篇】ThreadLocal源码解析(主打的就是通俗易懂,言简意赅)

文章目录 ThreadLocal学习笔记前言1、TheadLocal基本介绍2、ThreadLocal基本使用3、体验ThreadLocal的优点3.1 ThreadLocal与synchronized的比较3.2、ThreadLoca的应用场景 4、ThreadLocal的内部原理4.1 ThreadLocal内部结构4.2 ThreadLocal常用方法分析4.2.1 set原理分析4.2.2…

10.4K Star!程序员为程序员针对性优化的开源免费笔记

平时我一直用Notion来记录内容为主&#xff0c;但也一直关注着其他开源产品。上周正好看到一款非常受欢迎的开源免费笔记&#xff0c;今天就推荐给大家&#xff1a;VNote。 VNote一个由程序员为程序员打造的开源笔记应用&#xff0c;基于Qt开发&#xff0c;专注于使用 Markdown…

视觉三维重建第一课

0. 简介 对于视觉而言&#xff0c;想要获得比较精细的地图信息&#xff0c;这离不开地图的三维重建。三维重建&#xff08;3D Reconstruction&#xff09;的定义就是&#xff0c;从一堆二维图像中恢复物体的三维结构&#xff0c;并进行渲染&#xff0c;最终在计算机中进行客观…

【Math】特征值和奇异值辨析

奇异值和特征值都描述了一个矩阵的一些特性&#xff0c;但很多情况下&#xff0c;对于两者之间的区别和联系都不太清楚。 本文就这两者进行解析&#xff0c;并对奇异值的一些简单应用进行探索。 奇异值与特征值的定义 奇异值与特征值都被用于描述矩阵作用于某些向量的标量&am…

智能排水解决方案,设备实时监控+预测分析,真正实现“无人值守”!

什么是矿山排水 随着煤炭开采深度不断增加&#xff0c;地质条件也愈加复杂&#xff0c;井下综采作业会面临越来越高的渗水风险。为确保井下综采作业安全&#xff0c;需要设置大量排水系统&#xff0c;在矿山建设和生产过程中排除进入矿山的地下水和地表水。矿井排水系统是保障…

【C++】C++ 语言对 C 语言的加强 ① ( 实用性增强 - 变量任意位置定义 | register 关键字增强 - 自动进行寄存器优化 )

文章目录 一、实用性增强 - 变量任意位置定义二、register 关键字增强 - 自动进行寄存器优化 一、实用性增强 - 变量任意位置定义 C 语言定义变量位置 : 在 C 语言中 , 函数作用域中使用到的变量 , 必须在 作用域 开始的位置定义 , 一旦开始编写代码逻辑后 , 在逻辑代码行之间 …

【100天精通python】Day39:GUI界面编程_PyQt 从入门到实战(下)_图形绘制和动画效果,数据可视化,刷新交互

目录 专栏导读 6 图形绘制与动画效果 6.1 绘制基本图形、文本和图片 6.2 实现动画效果和过渡效果 7 数据可视化 7.1 使用 Matplotlib绘制图表 7.2 使用PyQtGraph绘制图表 7.3 数据的实时刷新和交互操作 7.3.1 数据的实时刷新 7.3.2 交互操作 7.4 自定义数据可视化…

vue实现穿梭框,ctrl多选,shift多选

效果图 代码 <template><div class"container"><!--左侧--><div><div class"title">{{ titles[0] }}</div><div class"layerContainer"><div v-for"item in leftLayerArray":key"…

Flink之时间语义

Flink之时间语义 简介 Flink中时间语义可以说是最重要的一个概念了,这里就说一下关于时间语义的机制,我们下看一下下面的表格,简单了解一下 时间定义processing time处理时间,也就是现实世界的时间,或者说代码执行时,服务器的时间event time事件时间,就是事件数据中所带的时…

LSTM模型

目录 LSTM模型 LSTM结构图 LSTM的核心思想 细胞状态 遗忘门 输入门 输出门 RNN模型 LRNN LSTM模型 什么是LSTM模型 LSTM (Long Short-Term Memory)也称长短时记忆结构,它是传统RNN的变体,与经典RNN相比能够有效捕捉长序列之间的语义关联,缓解梯度消失或爆炸现象.同时LS…

iOS自定义下拉刷新控件

自定义下拉刷新控件 概述 用了很多的别人的下拉刷新控件&#xff0c;想写一个玩玩&#xff0c;自定义一个在使用的时候也会比较有意思。使应用更加的灵动一些&#xff0c;毕竟谁不喜欢各种动画恰到好处的应用呢。 使用方式如下&#xff1a; tableview.refreshControl XRef…

【CTF-web】buuctf-[CISCN2019 华北赛区 Day2 Web1]Hack World(sql盲注)

题目链接 根据上图可知&#xff0c;页面中已经告诉我们要从flag表中的flag列取出flag&#xff0c;思考是sql注入。经过抓包发现发post包中的id字段是注入点。 经测试当输入id1时&#xff0c;结果为Hello, glzjin wants a girlfriend.&#xff0c;当id2时&#xff0c;结果为Do y…

Azure共享映像库构建VM镜像

什么是Azure共享映像库 Azure共享映像库是一项在Microsoft Azure中以共享方式存储和管理映像的服务。映像是预配置的虚拟机操作系统和应用程序的快照&#xff0c;可以用来创建多个虚拟机实例。通过将映像存储在共享映像库中&#xff0c;用户可以轻松地共享映像给其他Azure订阅…