重学C++系列之智能指针简单介绍

news2024/9/30 23:34:25

一、什么是智能指针

        在使用堆内存时,就像使用栈内存空间一样,可以实现自释放的功能,智能指针在C++库中也是类模板之一。

二、智能指针有几种

        有四种。auto_ptr, unique_ptr, shared_ptr, weak_ptr 其中后三个是C++11支持,第一个已经被C++弃用且被unique_ptr 代替,不推荐使用。

        1、unique_ptr, 实现了独占式拥有的概念,同一个时间只能有一个智能指针可以指向该对象,因为无法进行拷贝构造和拷贝赋值,但是可以进行移动构造和移动赋值。

        2、share_ptr, 实现了共享式拥有的概念,即多个智能指针可以指向相同的对象,该对象及相关资源会在其所指对象不再使用之后,自己释放与对象相关的资源。

        3、weak_ptr, 解决share_ptr相互引用时,两个指针的引用计数永远不会下降为0,从而导致死锁问题。而weak_ptr 是对对象的一种弱引用,可以绑定share_ptr, 但不会增加对象的引用计数。

        4、atuo_ptr, 实现独占式拥有的概念,同一时间只能有一个智能指针可以指向该对象;但atuo_ptr在C++17中被摒弃,其主要问题在于:对象所有权的转移,比如在函数传参过程中,对象所有权不会返还,从而存在潜在的内存崩溃问题;不能指向数组,也不能作为STL容器的成员。

三、智能指针的特点

        1、在C++库中也是类模板之一。

        2、实际上将指针封装在一个类,通过对象来管理指针。

        3、作用主要用来管理内存,在C++中,是一种管理资源,避免泄漏内存的习惯用法,也称RAII(资源获取及初始化)

四、案例

        1、auto_ptr的简单实现

#include <iostream>

using namespace std;


class Test1
{
private:
    int a;
public:
    Test1(int a = 0)
    {
        cout << "Test1()" << endl;
        this->a = a;
    }
    ~Test1()
    {
        cout << "~Test1()" << endl;
    }
    void show()
    {
        cout << "a = " << a << endl;
    }
};

class Test2
{
private:
    int a;
public:
    Test2(int a = 0)
    {
        cout << "Test2()" << endl;
        this->a = a;
    }
    ~Test2()
    {
        cout << "~Test2()" << endl;
    }
    void show()
    {
        cout << "a = " << a << endl;
    }
};

template <class T>
class myauto_ptr
{
private:
    T *ptr;
public:
    // 使用类模板的方式来适应多个类
    myauto_ptr(T *ptr = T ())
    {
        this->ptr = ptr;
    }

    ~myauto_ptr()
    {
        delete ptr;     // 重点在这里
        cout << "~myauto_ptr" << endl;
    }

    // 重载成员函数, 让本类的指针成员变量可以调用T类对象的成员函数
    T* operator ->()
    {
        return ptr;
    }

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




int main()
{
    Test1 *p1 = new Test1(10);
    // delete p1;   // 如果没有这步,会造成内存泄漏
    Test2 *p2 = new Test2(20);

    myauto_ptr<Test1> p3(new Test1(100));
    myauto_ptr<Test2> p4(new Test2(200));

    p3->show();
    (*p4).show();
    

    return 0;
}

        2、share_ptr的简单实现

#include <iostream>

using namespace std;

// 定义一个共享的全局变量,用来描述指向某个对象的指针个数
int share_count = 1;    

class Test1
{
private:
    int a;
public:
    Test1(int a = 0)
    {
        cout << "Test1()" << endl;
        this->a = a;
    }
    ~Test1()
    {
        cout << "~Test1()" << endl;
    }
    void show()
    {
        cout << "a = " << a << endl;
    }
};



template <class T>
class myshare_ptr
{
private:
    T *ptr;
public:
    // 使用类模板的方式来适应多个类
    myshare_ptr(T *ptr = T ())
    {
        this->ptr = ptr;
    }

    ~myshare_ptr()
    {
        cout << "count :" << share_count-1 << endl;
        if(this->ptr != nullptr && --share_count == 0)
        {
            delete ptr;     // 重点在这里
        }
        
        cout << "~myshare_ptr" << endl;
    }
    myshare_ptr(const myshare_ptr& other)
    {
        this->ptr = other.ptr;
        share_count++;
    }
    T& operator = (const myshare_ptr& other)
    {
        share_count++;
        this->ptr = other.ptr;
        return *this->ptr;
    }
    

    // 重载成员函数, 让本类的指针成员变量可以调用T类对象的成员函数
    T* operator ->()
    {
        return ptr;
    }

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




int main()
{
    Test1 *p1 = new Test1(10);
    // delete p1;   // 如果没有这步,会造成内存泄漏
    
    myshare_ptr<Test1> p2(new Test1(100));

    myshare_ptr<Test1> p3 = p2;
    myshare_ptr<Test1> p4 = p2;

    p3->show();
    

    return 0;
}

五、总结

        本篇只是简单讲解一下四种智能指针,并简单实现了两个简单的案例,实际使用中还是用C++提供的智能指针。了解内部原理有助于正确使用。

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

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

相关文章

递归:一个图教学会递归原理

递归的特点 实际上&#xff0c;递归有两个显著的特征,终止条件和自身调用: 自身调用&#xff1a;原问题可以分解为子问题&#xff0c;子问题和原问题的求解方法是一致的&#xff0c;即都是调用自身的同一个函数。终止条件&#xff1a;递归必须有一个终止的条件&#xff0c;即不…

软考A计划-系统集成项目管理工程师-项目人力资源管理-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

百度与AI:历史、投资和监管

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 百度的人工智能在中国具有先发优势 随着ChatGPT的爆火&#xff0c;人工智能重新引起了投资者的注意&#xff0c;然而人工智能并不是突然爆火的&#xff0c;而是全球众多公司在人工智能技术上进行数十年如一日的研发和积累&a…

Vite创建Vue+TS项目引入文件路径报错

使用vite搭建vue3脚手架的时候&#xff0c;发现main.ts中引入App.vue编辑器会报错&#xff0c;但是不影响代码运行。 报错信息&#xff1a;TS2307: Cannot find module ‘./App.vue’ or its corresponding type declarations. 翻译过来是找不到模块或者相关的声明类型&#…

发现问题:edge浏览器的效率模式会导致setTimeout/setInterval变慢

问题描述 当edge浏览器启用效率模式后&#xff0c;setTimeout/setInterval运行一段时间后&#xff0c;执行间隔会变慢。 开启后&#xff1a; 关闭效率模式&#xff1a;

pspice导入元件Orcad spice模型

想要使用英飞凌一款驱动芯片&#xff0c;型号&#xff1a;1EDN7550U&#xff0c;在贸泽等各大网站上都没有找到改元件的spice仿真模型&#xff0c;经过一番摸索&#xff0c;终于找到了。 1、首先去芯片官网上查找该元件&#xff1b;找到该元件的spice模型 2、下载下来&#xff…

第十一章:deque类

系列文章目录 文章目录 系列文章目录前言deque的介绍deque的使用deque的缺陷deque的应用总结 前言 deque是一种双开口的“连续空间”的容器。 deque的介绍 deque(双端队列)&#xff1a;是一种双开口的"连续"空间的数据结构&#xff0c;双开口的含义是&#xff1a;可…

消息中间件RabbitMQ——学习笔记

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

前端文件上传实践与后端处理——文件分块上传

文件上传是现代Web应用程序中常见的功能之一。在这篇博客中&#xff0c;我们将探讨一个简单但完整的前端文件上传实践&#xff0c;同时提供一个后端示例&#xff0c;演示如何处理上传的文件。我们将使用JavaScript作为前端语言&#xff0c;并结合Node.js作为后端环境。让我们开…

Jekins权限管理,给不同用户分配不同项目的权限【一些小细节真要注意】

首先进入jekins的系统管理界面&#xff1a; 一、插件安装 如果没有安装权限管理的插件&#xff0c;需要安装一个插件&#xff0c;插件的名字叫Role-based Authorization Strategy&#xff0c;进入插件管理中&#xff0c;选中这个插件&#xff0c;点击下面的安装就好了&#x…

java-day01(基本常识,环境搭建,注释,HelloWorld)

一&#xff1a;基础常识 软件&#xff1a;按照特定顺序的计算机数据与指令的集合。可分为系统软件&#xff08;如操作系统&#xff09;和应用软件&#xff08;如QQ&#xff09; 人机交互方式&#xff1a;图形化界面&#xff08;GUI&#xff09;与命令行&#xff08;CLI&#…

阿里大佬都内卷的 SpringBoot 从入门到实战笔记,太硬核了!

前言 这份 SpringBoot 实战文档&#xff0c;结合典型业务场景&#xff0c;全面介绍基于 Spring Boot 的核心开发技术&#xff0c;整合开源组件&#xff0c;一步一步地搭建微服务框架&#xff0c;实现微服务治理&#xff0c;详解 60 多个示例、2 个综合项目案例&#xff0c;提高…

低代码管理系统源码:只需简单编写配置文件即可构建企业级应用程序

一套可视化建模&#xff0c;描述式编程的企业应用程序开发平台。只需简单的点击鼠标&#xff0c;几乎任何人都可以创建功能强大的企业应用程序&#xff0c;实现业务流程自动化。企业创建的应用程序可以部署在移动&#xff0c;平板电脑和Web上&#xff0c;创建的应用程序可以很简…

使用Pytest生成HTML测试报告

背景 最近开发有关业务场景的功能时&#xff0c;涉及的API接口比较多&#xff0c;需要自己模拟多个业务场景的自动化测试&#xff08;暂时不涉及性能测试&#xff09;&#xff0c;并且在每次测试完后能够生成一份测试报告。 考虑到日常使用Python自带的UnitTest&#xff0c;所…

TPlink云路由器界面端口映射设置方法?快解析内网穿透能实现吗?

有很多网友在问&#xff1a;TPlink路由器端口映射怎么设置&#xff1f;因为不懂端口映射的原理&#xff0c;所以无从下手&#xff0c;下面小编就给大家分享TPlink云路由器界面端口映射设置方法&#xff0c;帮助大家快速入门TP路由器端口映射设置方法。 1.登录路由器管理界面&a…

Visual Studio 2022 程序员必须知道高效调试手段与技巧(下)终章

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言&#x1f4ac; 一些调试的实例&#x1f4ad; 实例一&#x1f4fa; 调试演示 &#x1f4ad; 实…

24考研数据结构-第一章 绪论

数据结构 引用文章第一章&#xff1a;绪论1.0 数据结构在学什么1.1 数据结构的基本概念1.2 数据结构的三要素1.3 算法的基本概念1.4 算法的时间复杂度1.4.1 渐近时间复杂度1.4.2 常对幂指阶1.4.3 时间复杂度的计算1.4.4 最好与最坏时间复杂度 1.5 算法的空间复杂度1.5.1 空间复…

freeswitch的mod_xml_curl模块

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 随着fs服务的增多&#xff0c;每一台fs都需要在后台单独配置&#xff0c;耗时耗力&#xff0c;心力憔悴。 如果有一个集中管理配置的配置中心&#xff0c;统一管理所有fs的配置&#xff0c;并可以实现动态的修改配置就…

STUN工作原理

目录 一. 前言 二. STUN报文格式 STUN Header RFC3489 RFC5389 STUN Message Body RFC3489 RFC5389 三. WebRTC对STUN协议的支持 四. STUN工作流程 1. 使用STUN获取NAT映射后的地址 五. 参考资料 一. 前言 现实网络环境中绝大多数主机都是处于 NAT 之后&#xff0c…

华为数通HCIP-VPN技术-mpls vpn

VPN(虚拟专线网络 作用&#xff1a;实现广域互联&#xff08;不同地域局域网之间跨越公网进行互通&#xff09;&#xff1b; MPLS VPN 设备角色&#xff1a; PE&#xff08;运营商边界设备&#xff09;&#xff1a; CE&#xff1a;VPN用户企业的边界设备 P:运营商 VPN实例…