智能指针之设计模式2

前面介绍了工厂模式控制了智能指针和资源对象的创建过程,现在介绍一下智能指针是如何利用代理模式来实现“类指针(like-pointer)”的功能,并控制资源对象的销毁过程的。

2、代理模式

代理模式是为其它对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不直接引用另一个对象,而是通过一个代理对象在客户端和目标对象之间起到中介的作用,这个代理对象提供了和目标对象完全一样的功能接口,客户端访问这个代理对象就像是在访问目标对象一样,同时代理对象根据需要在访问目标对象时进行了控制。智能指针就起到了客户端和裸指针的中介代理作用。

按照GOF的说法,组成代理模式的角色有:
主题角色(Subject):定义了代理角色和真实角色的共用接口方法,这样在任何使用真实角色的地方都有可以使用代理角色。
代理角色(Proxy):实现主题角色接口方法,是真实角色的代理,通过真实角色的业务逻辑方法来实现主题角色的接口方法,并可以附加自己的操作,对真实角色的行为进行控制。
真实角色(RealSubject):实现主题角色接口方法,定义了真实角色所要实现的业务逻辑,供代理角色调用。

代理模式的类结构如下图所示:
在这里插入图片描述

智能指针使用面向对象技术封装了C++中的裸指针,是裸指针的包装类,它按照RAII惯用法来管理指针资源,可以在失去生存期时同时把所管理的资源释放掉,得益于C++的操作符重载,智能指针提供了*、->等操作符,它的行为就像是指针,可以按照指针的形式来对智能指针对象进行操作,比如使用“*”操作符来解引用所指向的内容,使用“->”操作符来访问所指向的结构对象的成员,就像是在操作一个普通指针一样。

我们不妨脑洞大开一下,如果把“指针”当作是一种对象,使用面向对象进行设计的话,可以大体定义成类似下面的class:

template<typename T>
class pointer {
private:T *address; // 数据成员public:pointer(T *p);// 下面是成员函数T *operator++();T *operator--();T *operator+=(int offset);T *operator-=(int offset);T operator*();T operator[int index];T *operator->();delete();
}

再看unique_ptr和shared_ptr类,可以把它们当作是pointer基类的派生类,它们提供了pointer定义的成员方法,并且还包含了一个pointer指针。

以shared_ptr为例,可以视为下面的class:

class shared_ptr : public pointer {
private:pointer ptr; // 资源对象指针,指向被代理对象ref_count *refcnt; // 引用计数
public:shared_ptr(pointer p) {...其它操作ptr = p;}T operator*() {return *ptr;}T *operator->() {return ptr;}~shared_ptr() {...其它操作ptr->delete();}...其它成员函数
}

从类的结构形式上看,shared_ptr类继承于pointer类,并且拥有一个pointer类型的数据成员,正好符合代理模式的类结构图:基类pointer对应subject主题类,而shared_ptr类对应proxy代理类,shared_ptr还包含了一个类型为基类pointer的数据成员ptr,即被代理对象,在实践中就是裸指针。再看shared_ptr的功能,它public继承了pointer类,因此它对外提供了pointer类的接口,例如解引用操作符*和成员访问操作符->,当调用shared_ptr的这些接口时,它会把请求转发到数据成员ptr的对应接口上。同时它也对相关的接口做了控制,比如为了防止访问内存越界,没有提供指针的算术运算,更重要的是,它控制了资源对象的生存期管理,比如,只有在引用计数为0时才释放资源对象,这也正是智能指针的重要功能。也就说,shared_ptr对内包含了一个指针类型成员,对外又表现为一个指针类型,而且还对指针成员的行为做出了控制。这不正是代理模式吗?

由此可见,智能指针unique_ptr和shared_ptr的实现正是代理模式的典型应用。当然,如果严格地按照面向对象编程的特征,因为C++中没有“指针”类,指针只是C++固有的基本类型,可能不是标准的代理模式,虽然外在形式上不同,但确实表现出了代理模式的思想和意图:提供了与裸指针相同的功能,并把请求转发给裸指针处理,同时对裸指针的操作进行了控制(如不提供某种操作,或者限制使用),最核心的控制是能够对裸指针指向的资源对象进行了生存期管理。

此外,C++中还有另一种形式的“类指针”对象:迭代器,它也实现了*、->等操作符函数,而且还提供了++、–、+=、-=等算术操作符,对照代理模式来分析,它也是使用代理模式来实现的(注:它是标准的迭代器模式,这里关注的是它的“类指针”特性)。不过,智能指针作为指针的代理对象,控制的是被代理对象——指针的生存期管理,而迭代器作为“集合指针”(如指向数组的指针)的代理对象,控制的是对所代理的集合指针的遍历访问行为,可以不用关心底层的数据存储方式,同时控制访问时不会越界,显然它的核心功能是指针的算术操作,因为容器里存放的都是对象集合,不止一个,为迭代器提供指针的算术运算操作再正常不过了。

总之,尽管指针在编程使用时,容易发生内存泄漏、指针越界、野指针、重复释放等错误。但是通过它的代理对象-智能指针,可以很好的控制指针的行为,尽可能的避免了一些错误的发生。

如果说智能指针使用工厂模式控制了资源对象的创建过程,那它使用代理模式控制了资源对象的销毁过程:可以控制它在智能对象失去生存期时也立即销毁资源对象,如unique_ptr,也可以控制它在最后一个引用它的智能指针对象失去生存期时再销毁,如shared_ptr。

智能指针又是怎样释放资源对象的呢?下一篇文章介绍所使用的另一种设计模式。

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

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

相关文章

探索R语言:在线学习资源汇总

一、收集关于特定R主题的问题和答案&#xff08;Q&A&#xff09; 1. Stack overflow Empowering the world to develop technology through collective knowledge – Stack Overflowhttps://stackoverflow.co/ 二、Rstudio工具栏help Rstudio中有个Cheat sheet&#xf…

《C语言中以数组作为参数的探讨》

&#x1f680;个人主页&#xff1a;BabyZZの秘密日记 &#x1f4d6;收入专栏&#xff1a;C语言 &#x1f30d;文章目入 一、数组作为参数的传递机制二、数组参数的声明方式&#xff08;一&#xff09;省略数组大小&#xff08;二&#xff09;指定数组大小&#xff08;三&#x…

深入解析区块链技术:原理、应用与未来展望

1 区块链技术原理 1.1 基本概念 区块链本质上是一个分布式账本&#xff0c;它由一系列按照时间顺序排列的数据块组成&#xff0c;每个数据块包含了一定时间内的交易信息。这些数据块通过密码学技术相互链接&#xff0c;形成一个不可篡改的链条。其核心特点包括去中心化、不可篡…

selenium快速入门

一、操作浏览器 from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By# 设置选项 q1 Options() q1.add_argument("--no-sandbo…

面试如何应用大模型

在面试中,如果被问及如何应用大模型,尤其是面向政务、国有企业或大型传统企业的数字化转型场景,你可以从以下几个角度进行思考和回答: 1. 确定应用大模型的目标与痛点 首先,明确应用大模型的业务目标,并结合企业的实际需求分析可能面临的痛点。这些企业通常会关注如何提…

嵌入式常见概念的介绍

目录 一、MCU、MPU、ARM &#xff08;一&#xff09;MCU&#xff08;微控制器&#xff09; &#xff08;二&#xff09;MPU&#xff08;微处理器&#xff09; &#xff08;三&#xff09;ARM&#xff08;架构&#xff09; 二、DSP &#xff08;一&#xff09;数字信号处理…

深度强化学习(DRL)框架与多目标调度优化详解

深度强化学习&#xff08;DRL&#xff09;框架与多目标调度优化详解 &#xff08;截至2025年4月&#xff0c;结合最新研究进展&#xff09; 一、DRL主流框架及核心算法 通用DRL框架 Ray RLlib&#xff1a;支持分布式训练&#xff0c;集成PPO、A3C、DQN等算法&#xff0c;适用于…

centos 安装python3.9.9

这里写自定义目录标题 安装编译依赖 sudo yum -y groupinstall "Development Tools" sudo yum -y install openssl-devel bzip2-devel libffi-devel wget zlib-devel yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel …

【动态规划】深入动态规划:背包问题

文章目录 前言01背包例题一、01背包二、分割等和子集三、目标和四、最后一块石头的重量|| 完全背包例题一、完全背包二、 零钱兑换三、零钱兑换||四、完全平方数 前言 什么是背包问题&#xff0c;怎么解决算法中的背包问题呢&#xff1f; 背包问题 (Knapsack problem) 是⼀种组…

Vue 接口请求 Nginx配置实时压缩 速度起飞

生效之前 nginx配置如下 gzip on; gzip_min_length 1k; gzip_buffers 16 256k; gzip_http_version 1.1; gzip_comp_level 6; gzip_types application/json application/javascript text/javascript text/css text/plain; gzip_vary on; 生效之后 #user…

Mitosis:跨框架的UI组件解决方案

Mitosis 是一个开源工具&#xff0c;可以将 JSX 组件转换为 Angular、React、Qwik、Vue、Svelte、Solid 和 React Native 等框架的功能齐全的组件。 Stars 数13019Forks 数593 主要特点 跨框架兼容性&#xff1a;Mitosis 允许开发者编写一次组件&#xff0c;然后编译成多个主流…

齐次坐标系统:什么是齐次坐标?为什么要引入齐次坐标?

齐次坐标系统&#xff1a;计算机图形学的基础 在计算机图形学、计算机视觉、相机标定、三维建模等领域&#xff0c;齐次坐标是一个非常重要的数学工具。本文将介绍&#xff1a;齐次坐标的基本概念、数学原理、我们为什么要引入齐次坐标、及其在实际应用中的价值。 文章目录 齐…

JS的大数运算(注意:原生的只支持整数计算!!!)

JS的大数运算&#xff08;注意&#xff1a;原生的只支持整数计算&#xff01;&#xff01;&#xff01;&#xff09; 一、JS的大数运算&#xff08;注意&#xff1a;原生的只支持整数计算&#xff01;&#xff01;&#xff01;&#xff09;1. 数字精度限制2. 大数解决方案2.1. …

Android 之美国关税问题导致 GitHub 403 无法正常访问,责任在谁?

这几天各国关税问题导致世界动荡不安&#xff0c;如今GitHub又无法正常访问&#xff0c;是不是Google到时候也无法正常使用了。

JAVA中正则表达式的入门与使用

JAVA中正则表达式的入门与使用 一&#xff0c;基础概念 正则表达式&#xff08;Regex&#xff09; 用于匹配字符串中的特定模式&#xff0c;Java 中通过 java.util.regex 包实现&#xff0c;核心类为&#xff1a; Pattern&#xff1a;编译后的正则表达式对象。 Matcher&#…

Prompt_Engineering提示词工程(一)

一、Prompt&#xff08;提示词&#xff09; Prompt&#xff08;提示词&#xff09;是给AI模型交互文本片段&#xff0c;用于指导模型生成符合预期输出结果&#xff0c;提示词的目的是为模型提供一个上下文的任务&#xff0c;以便模型能够更准确地理解用户的意图&#xff0c;并…

【设计模式】面向对象开发学习OOPC

PLOOC-裸机思维 PLOOC-git OOPC精要——撩开“对象”的神秘面纱 C/C面向对象编程之封装-KK 面向过程&#xff0c;本质是“顺序&#xff0c;循环&#xff0c;分支”面向对象&#xff0c;本质是“继承&#xff0c;封装&#xff0c;多态”参考的书籍&#xff1a;《UMLOOPC嵌入式…

软考高级--案例分析

架构风格 重点 交互方式数据结构控制结构扩展方法 分类 管道-过滤器风格 数据流 数据仓储风格 星型结构以数据为中心&#xff0c;其他构件围绕数据进行交互 企业服务总线esb 定义 以一个服务总线充当中间件的角色&#xff0c;把各方服务对接起来&#xff0c;所有服务…

01_背包问题

package org.josh; import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner new Scanner(System.in); int n scanner.nextInt(); // 物品数量 long w scanner.nextLong(); // 背包容量&#xff0c;使用long防止溢出 int[] v …

esp32-idf Linux 环境安装教程

一、提前说明 1. 系统环境 Ubuntu22.04 2. 适配芯片 ESP32S3 3. idf版本 v5.4.1(截止2025年4月13日为最新版本) 二、安装步骤 1. 安装前置依赖 sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev l…