c++学习:智能指针的底层作用原理+用法

news2025/1/18 20:56:02

目录

智能指针作用原理

作用

原理

模仿int*类型的智能指针

模仿所有类型的智能指针(模板)

共享智能指针类

思考;如果多个智能指针同时指向同一个堆空间,怎么只执行一次析构函数进行释放空间   (共享智能指针类)

独占式智能指针

c++提供的标准智能指针

头文件

标准智能指针模板类的成员类型和成员函数

用法


智能指针作用原理

如果分配了一个内存空间,但后面又忘记释放空间,会造成内存泄漏,智能指针就可以自动释放空间,避免内存泄漏。

智能指针是一个RAII类模型,用于动态分配内存,其设计思想是将基本类型指针封装为(模板)类对象指针,并在离开作用域时调用析构函数,使用delete删除指针所指向的内存空间。

作用

能够处理内存泄漏问题和空悬指针问题

原理

像类一样,有构造函数和析构函数,当申请的时候就是构造函数,当不用了,就自动运行析构函数来释放空间

模仿int*类型的智能指针

class shared_ptr
{
public:
    //等价于int *p = new int(100)
    shared_ptr(int*p):ptr(p){}
    ~shared_ptr()
    {
        cout<<__FUNCTION__<<endl;
        if(this->ptr != NULL)
        {
            delete this->ptr;
        }
    }
    int*get()
    {
        return this->ptr;
    }
private:
    int*ptr;
};

void test()
{
    //正常申请内存空间
    int *p = new int(100);
    *p = 200;
    cout<<*p<<endl;
    delete p;

    //模仿智能指针申请内存空间
    shared_ptr p1(new int(100));
    *(p1.get()) = 200;
    cout<<*(p1.get())<<endl;
}

模仿所有类型的智能指针(模板)

template<class T>
class shared_ptr
{
public:
    //int *p = new int(100)
    shared_ptr(T*p):ptr(p){}
    ~shared_ptr()
    {
        cout<<__FUNCTION__<<endl;
        if(this->ptr != NULL)
        {
            delete this->ptr;
        }
    }
    T*get()
    {
        return this->ptr;
    }
private:
    T*ptr;
};

//例子 :申请一个类的智能指针
class Demo
{
public:
    Demo()
    {
        cout<<"Demo()"<<endl;
    }
    ~Demo()
    {
        cout<<"~Demo()"<<endl;
    }
private:
    int data;
};

void test01()
{
    shared_ptr<Demo> p1(new Demo);
}

共享智能指针类

思考;如果多个智能指针同时指向同一个堆空间,怎么只执行一次析构函数进行释放空间   (共享智能指针类)

解决办法:每当有一个智能指针指向一个堆空间,就记录一次,当有第二个智能指针指向该空间,就+1,每当一个智能指针执行析构函数的时候就-1,判断是否是最后一个指向该空间的智能指针再决定释放空间 

template<class T>
class shared_ptr
{
public:
    //int *p = new int(100)
    shared_ptr(T*p):ptr(p){}
    shared_ptr(shared_ptr &ra)
    {
        ptr = ra.ptr;
        count++;
    }
    ~shared_ptr()
    {
        cout<<__FUNCTION__<<endl;
        if(this->ptr != NULL && --count == 0)
        {
            //最后一个对象被销毁的时候,才执行里面的代码
            delete this->ptr;
            this->ptr = NULL;
            cout<<"count == 0"<<endl;
        }
    }
    T*get()
    {
        return this->ptr;
    }
private:
    T*ptr;
    static int count;//要在类外定义初始化
};

template<class T>
int shared_ptr<T>::count=0;

class Demo
{
public:
    Demo()
    {
        cout<<"Demo()"<<endl;
    }
    ~Demo()
    {
        cout<<"~Demo()"<<endl;
    }
    void setData(int d)
    {
        data = d;
    }
private:
    int data;
};

void test01()
{
    //多个智能指针类的对象可以管理 同一个堆空间
    shared_ptr<Demo> p2(new Demo);
    shared_ptr<Demo> p3(p2);
    shared_ptr<Demo> p4(p3);
    shared_ptr<Demo> p5(p4);

    p2.get()->setData(100);
}

独占式智能指针

 如果是独占式智能指针,shared_ptr<Demo> p3(p2);这种写法会报错,因为智能有一个智能指针指向该堆空间

template<class T>
class unique_ptr
{
    //方法1:将拷贝构造函数声明为私有,外面的无法调用
    //unique_ptr(unique_ptr &ra);
public:
    unique_ptr(T*p):ptr(p){}
    //方法2:在拷贝构造函数的声明后面加上delete关键字 ,表示这个函数不能被调用
    unique_ptr(unique_ptr &ra) = delete;
    ~unique_ptr()
    {
        cout<<__FUNCTION__<<endl;
        if(this->ptr != NULL)
        {
            delete this->ptr;
            this->ptr = NULL;
        }
    }
    T*get()
    {
        return this->ptr;
    }
private:
    T*ptr;
    static int count;//要在类外定义初始化
};

c++提供的标准智能指针

头文件

#include <memory> 

标准智能指针模板类的成员类型和成员函数

std::shared_ptr - cppreference.comicon-default.png?t=N7T8https://zh.cppreference.com/w/cpp/memory/shared_ptr

用法

#include <iostream>
#include <memory> //C++智能指针类的头文件

using namespace std;

int main()
{
    shared_ptr<int> ptr1(new int(120));

    *(ptr1.get()) = 1000;

    unique_ptr<char> ptr2(new char);

    return 0;
}

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

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

相关文章

井盖异动传感器,守护脚下安全

随着城市化进程的加速&#xff0c;城市基础设施的安全问题日益受到关注。其中&#xff0c;井盖作为城市地下管道的重要入口&#xff0c;其安全问题不容忽视。然而&#xff0c;传统的井盖监控方式往往存在盲区&#xff0c;无法及时发现井盖的异常移动。为此&#xff0c;我们推出…

Cesium笔记 初始化 使用Vue-Cesium 组件

参考 A Vue 3 based component library of CesiumJS for developers | Vue for CesiumVue for Cesium, a Vue 3.x based component library of CesiumJS for GISerhttps://zouyaoji.top/vue-cesium/#/zh-CN/component/quickstart

HTML---JQurey的基本使用

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 本章目标 &#xff08;1&#xff09;能够搭建jQuery开发环境 &#xff08;2&#xff09;使用ready( )方法加载页面、掌握jQuery语法 使用addClass( )方法和css( )方法为元素添加CSS样式使用n…

vue elementUI Tree 树形控件的使用方法

用清晰的层级结构展示信息&#xff0c;可展开或折叠。 效果演示 trees.vue代码 <template><div><!-- 树形控件 --><el-tree :data"treesList" :props"treesProps" show-checkbox node-key"id"default-expand-all :defau…

【C++】十大排序算法

文章目录 十大排序算法插入排序O(n^2^)冒泡排序O(n^2^)选择排序O(n^2^)希尔排序——缩小增量排序O(nlogn)快速排序O(nlogn)堆排序O(nlogn)归并排序(nlogn)计数排序O(nk)基数排序O(n*k)桶排序O(nk) 十大排序算法 排序算法的稳定性&#xff1a;在具有多个相同关键字的记录中&…

如何实现两台Linux虚拟机ssh免密登录

实验开始前 1.准备好两台虚拟机&#xff08;下载好镜像文件的&#xff09; 2.实验步骤 公钥验证&#xff1a;&#xff08;免密登陆验证方式&#xff09; &#xff08;1&#xff09;生成非对称秘钥 [rootclient ~]# ssh-keygen -t rsa Generating public/private rsa key pai…

系统性介绍MoE模型架构,以及在如今大模型方向的发展现状

知乎&#xff1a;Verlocksss编辑&#xff1a;马景锐链接&#xff1a;https://zhuanlan.zhihu.com/p/675216281 1 学习动机 第一次了解到MoE&#xff08;Mixture of experts&#xff09;&#xff0c;是在GPT-4模型架构泄漏事件&#xff0c;听说GPT-4的架构是8个GPT-3级别大小的模…

IBM DS5020硬盘状态Impending failure(reported by controller)

这个状态说明硬盘还没有完全坏掉&#xff0c;但是也需要注意更换新硬盘了 磁盘状态详细信息&#xff1a; 报错信息 按照恢复步骤&#xff1a; 选中该硬盘&#xff0c;手动failed&#xff0c;之后可以将该硬盘拔掉&#xff0c;重新插入新硬盘 此时&#xff0c;会有一块热备盘启…

【npm link】Node命令中的npm link命令的使用,还有CLI全局命令的使用,开发命令行工具必不可少的部分

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;NodeJs &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续前进的勇气…

Linux网络的命令和配置

目录 一、网络配置命令 1、配置和管理网络接口 1.1 ifconfig 1.2 ip 1.2.1 ip link 1.2.2 ip addr 1.3 修改网络接口名 1.3.1 临时修改网络接口名 1.3.2 永久修改网络接口名 1.4 永久配置单网卡 1.5 永久配置双网卡 1.6 ethtool 2、查看和设置主机中路由表信息…

使用kubesphere的devops部署SpringCloud项目

devops部署SpringCloud项目 环境说明部署流程创建DevOps工程填写流水线信息创建流水线jenkinsfileDockerfiledeploy.yaml 环境说明 已经安装kubesphere的devops组件安装教程可参考官方文档:https://v3-1.docs.kubesphere.io/zh/docs/pluggable-components/devops/ 部署流程 创…

Ubuntu系统下安装TDengine Database

记录一下使用Ubuntu系统的安装TDengine Database管理软件工具 先查看一下系统的版本&#xff0c;可以看到这里使用的是Ubuntu20.04版本&#xff0c;版本代号focal mywmyw-S451LN:~$ uname -a Linux myw-S451LN 6.2.0-39-generic #40~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu …

一键搭建elk

一键启动elk 1. 生成环境的脚本 setup.sh #!/usr/bin/bash# logstash enviroment mkdir -p logstash touch logstash/logstash.conf # shellcheck disableSC1078 echo input {tcp {mode > "server"host > "0.0.0.0"port > 4560codec > jso…

Kubernetes WebHook 入门 -- 入门案例: apiserver 接入 github

博客原文 文章目录 k8s 集群配置介绍Admission WebhookWebHook 入门实践: github 认证接入web 服务器Dockerfile 镜像制作amd64x86_64构造镜像检验镜像 Makefilewebhook 接入 apiserverwebhook.yamlapiserver 挂载 webconfig在 github 中创建认证 token将 token 添加到 kubecon…

以某一web系统为测试对象(若依RuoYi为例)-软件测试实验报告作业

题目:以某一 web系统为测试对象&#xff0c;完成以下文档的编写(满分 100分) (1)产品规格说明书 (SPEC) 要求:功能完整(完成产品需求 70%以上)、UI 优良 (每个页面均有字段约 束和合理的出错提示)、流程完整 (一一对应功能)流程合理 (处理逻辑非直线) (2)测试计划要求 :测试进…

一、数据结构基本概念

数据结构基本概念 一、数据结构基本概念1.基本概念和术语1.1数据&#xff08;Data&#xff09;1.2 数据元素&#xff08;Data element&#xff09;1.3 数据项 &#xff08;Data Item&#xff09;1.4 数据对象 &#xff08;Data Object&#xff09;1.5 数据结构 &#xff08;Dat…

移除两个双向链表中的重复元素,每个链表中的元素不重复

移除两个双向链表中的重复元素&#xff0c;每个链表中的元素不重复&#xff0c;请给出算法。 ans: 该问题比单向链表要更加复杂一些&#xff0c;必须考虑并更新前向节点的指向情况&#xff0c;具体编码中存在一些难度&#xff0c;加上链表调试相对不容易&#xff0c;因此难度系…

Qt之有趣的数字钟

一.效果 基于网络代码修改,支持时、分、秒;支持滑动、翻页和旋转。 二.实现 #include <QtCore> #include <QPainter> #include <QAction> #include <QWidget> #include <QMainWindow> #include <QTimer> #include <QKeyEvent> #…

React ant table警告:Each child in a list should have a unique “key“ prop.

如下图&#xff1a; 原因 React Ant table表格每一行都需要一个唯一标识来确保不重复&#xff0c;如果不加该属性&#xff0c;就会出现这个警告。 修复 添加这一行&#xff1a; rowKey{(record) > record.id} # id为行idTable代码段&#xff1a; <TabledataSourc…

Armv8-R AArch32 architecture概念学习

提示 该博客主要为个人学习&#xff0c;通过阅读官网手册整理而来&#xff08;个人觉得阅读官网的英文文档非常有助于理解各个IP特性&#xff09;。若有不对之处请参考参考文档&#xff0c;以官网文档为准。阅读该文章&#xff0c;可以先查看AArch64 Exception Model学习&…