智能指針之設計模式3

這次我們看一下智能指針是如何使用策略模式來釋放資源的,同時又是如何擴展功能,管理更多的資源對象類型的。

3、策略模式

策略模式作為一種軟件設計模式,指對象有某個行為,但是在不同的應用場景中,該行為有不同的實現算法。它的意圖是:定義一系列算法,把它們一個個封裝起來,并且使它們可相互替換,算法可獨立于使用它的客戶而變化。

下面是它的結構圖:
在這里插入圖片描述
組成結構:
—Strategy(抽象策略角色): 策略類,定義算法的公共接口。
—ConcreteStrategy(具體策略角色):具體策略類,實現某種具體算法。
—Context(環境上下文角色):持有一個策略類的引用,最終給客戶端調用。

本質上就是在C++中,一個Strategy基類定義了虛函數(即算法),它的不同ConcreteStrategy派生類重寫了虛函數的實現,而Context類中有一個Strategy引用類型的數據成員,可以存放不同的派生類對象,Context調用基類數據成員的虛函數時,并不知道數據成員的實際類型,顯然這是面向對象動態綁定機制。因為是Context只依賴于Strategy基類類型,根據里氏替換原則,各個繼承于Strategy的派生類ConcreteStrategy對象可以互相替換,不會對Context有任何影響。

我們看一下智能指針的刪除器,它的功能是為智能指針提供釋放資源的方法,有不同的形式和類型,智能指針會在它的reset()成員函數和析構函數中調用刪除器,也不關心是什么形式的刪除器,只要能調用它的void operator()(T *ptr)操作符就行。

我們再次腦洞大開一下,把一個提供了形如void operator()(T *ptr)調用操作符的函數對象類看作是策略基類,它定義了具體策略類所要實現的接口功能。如同上一篇文章中使用面向對象技術把指針封裝成一個類一樣,同樣,現在也把刪除器封裝成一個函數對象類,作為抽象策略基類。如下所示:

class deleter {
public:void operator()(T *ptr);
}

該類對象的核心功能是:void operator()(T *ptr),等同于策略模式中的算法,供智能指針對象調用來銷毀資源對象,只要一個類提供了參數是指針類型沒有返回值的可調用操作符,都可以算作是它的派生類。

顯然,對于普通函數:

void deleter_func(T *ptr) {delete ptr;
}

函數對象:

class deleter_func_obj {
public:void operator()(T *ptr) {delete ptr;}
}

lambda表達式:

auto deleter_lambda = [](T *ptr) {delete ptr};

以及function對象:

function<void(T *ptr)> func = bind(xxxx);

它們都提供了符合要求的可調用對象的函數接口,用面向對象術語的話,可以說它們都是deleter類的派生類,它們都被看作是具體的策略類對象,提供了不同的算法。那么在創建unique_ptr或者shared_ptr對象時,均可以選擇一個作為參數傳入,它們是可以互相替換的。顯然,這正是策略模式背后所體現的思想,可以讓智能指針靈活地支持多種類型的刪除器,在這里,智能指針unique_ptr和shared_ptr對應了context環境角色,而刪除器deleter對應了stragety策略角色。

這種模式的好處:

首先,可以使用不同形式的刪除器。
顯然,可以使用函數指針、函數對象、lambda表達式,以及function對象等不同形式來創建deleter對象,不管它們的外在形式如何,只要實現了void (T *ptr)方法,都可以在創建智能指針時選擇一個作為策略對象傳入,在需要的時候調用它們。

其次,可以擴展智能指針的功能。
策略模式中,可以把context角色類比為一個基類對象,而strategy角色就是派生類對象要實現的虛函數,只不過不是通過繼承基類來實現虛函數功能,而是把要實現的虛函數封裝成strategy對象,然后傳入contex中去回調,顯然這樣也等同于使用不同的stragety擴展了context的不同功能。

我們知道,智能指針可以管理不同形式的資源,資源對象可以是數組,可以是普通對象、可以來自堆中,可以來自系統調用,在釋放時,有的需要使用delete操作符,有的需要使用free()函數,有的需要使用close()函數。比如unique_ptr類,它是C++標準庫提供的類型,無法修改它的源碼,它是怎樣做到能夠管理更多的資源的?

看一下deleter角色,它的接口需要一個參數T *ptr,這個參數就是智能指針對象所管理的資源對象,在調用deleter時由智能指針作為參數傳入ptr。因此,deleter知道ptr的類型信息,完全可以使用ptr做一些具體的算法邏輯操作,這就相當于擴展了智能指針對象的功能:只要deleter對象根據參數類型實現了不同的功能,智能指針又調用deleter,不就是等同于它通過deleter實現了該功能嗎?可以腦補想象一下:智能指針類中有一個虛函數,它通過this指針來訪問ptr數據成員,并實現了相關的功能。

傳入不同的deleter對象,也等同于擴展了智能指針的不同功能。這樣,智能指針不但可以管理內存資源,而且可以管理句柄、socket、文件指針、文件描述符等其它形式的資源。

下面一個演示,通過lambda表達式實現了關閉文件指針的操作,unique_ptr使用它擴展了自己的功能:也可以管理FILE文件指針資源了。

FILE *file = fopen("/tmp/tmp.txt", "r"); // 分配FILE資源
unique_ptr<FILE, void(*)(FILE *)> fup(file, [](FILE *file) {fclose(file);
});

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80626.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80626.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80626.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

華為盤古OS深度評測:構建AI自進化系統的實踐密碼

華為盤古OS通過分布式AI內核與自適應學習框架的深度耦合&#xff0c;重新定義操作系統級智能能力。實測顯示其AI任務調度效率較傳統系統提升17倍&#xff0c;本文從智能體編排、持續學習機制、端云協同架構三個維度&#xff0c;解析如何基于DevKit 3.0打造具備認知進化能力的下…

精益數據分析(28/126):解讀商業模式拼圖與關鍵指標

精益數據分析&#xff08;28/126&#xff09;&#xff1a;解讀商業模式拼圖與關鍵指標 在創業和數據分析的探索旅程中&#xff0c;每一次深入研究都可能帶來新的啟發和突破。今天&#xff0c;我們依舊帶著共同進步的初心&#xff0c;深入解讀《精益數據分析》中關于商業模式的…

GitLab Runner配置并行執行多個任務

檢查并修改方法&#xff1a; 打開 Runner 的配置文件&#xff08;通常位于 /etc/gitlab-runner/config.toml 或 ~/.gitlab-runner/config.toml&#xff09;。 確保 concurrent 值大于 1&#xff0c;例如&#xff1a; concurrent 4 # 允許最多 4 個任務同時運行重啟 Runner…

開發首個Spring Boot應用

&#x1f4cb; 前置條件 &#x1f3af; 在開始之前&#xff0c;請打開終端并運行以下命令以確保已安裝正確版本的 Java&#xff1a; $ java -version openjdk version "17.0.4.1" 2022-08-12 LTS OpenJDK Runtime Environment (build 17.0.4.11-LTS) OpenJDK 64-Bi…

【信息系統項目管理師】高分論文:論質量管理和進度管理(智慧旅游平臺建設項目)

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 論文1、規劃質量管理2、質量保證3、質量控制論文 2019年3月,我作為項目經理,參加了某市智慧旅游平臺建設項目,負責項目的全面管理, 該項目以打造一流的國內外生態旅游城市為目標,旨在大數據云平臺建設的基…

DAM-3B,英偉達推出的多模態大語言模型

DAM-3B是什么 DAM-3B&#xff08;Describe Anything 3B&#xff09;是英偉達推出的一款多模態大語言模型&#xff0c;專門用于為圖像和視頻中的特定區域生成詳細描述。用戶可以通過點、邊界框、涂鴉或掩碼等方式來標識目標區域&#xff0c;從而得到精準且符合上下文的文本描述…

如何判斷你的PyTorch是GPU版還是CPU版?

如何判斷你的PyTorch是GPU版還是CPU版&#xff1f; PyTorch作為當前最流行的深度學習框架之一&#xff0c;支持在CPU和GPU(NVIDIA CUDA)上運行。對于深度學習開發者來說&#xff0c;正確識別PyTorch版本至關重要&#xff0c;因為GPU版本可以帶來10-100倍的性能提升。本文將全面…

Gin框架

Gin 快速入門 go get -u github.com/gin-gonic/gin package main import gin "github.com/gin-gonic/gin"func main() {engine : gin.Default()engine.GET("/", func(c *gin.Context) {c.String(200, "Hello Gin")})engine.Run(":8888&q…

【Project】基于spark-App端口懂車帝數據采集與可視化

文章目錄 hadoop完全分布式部署hdfs-site.xmlcore-site.xmlmarpred-site.xmlyarn-site.xml spark集群部署spark-env.sh mongodb分片模式部署config 服務器初始化config 副本集 shard 服務器初始化shard 副本集 mongos服務器添加shard設置chunk大小 啟動分片為集合 user 創建索引…

brew 安裝openjdk查看其版本

使用brew&#xff08;如果你使用Homebrew安裝&#xff09; 如果你通過Homebrew安裝了OpenJDK&#xff0c;可以使用以下命令來查看安裝的版本,&#xff1a; brew list --versions openjdk8 這將會列出所有通過Homebrew安裝的OpenJDK版本及其版本號。 3. 查看/usr/libexec/ja…

【Linux網絡】構建與優化HTTP請求處理 - HttpRequest從理解到實現

&#x1f4e2;博客主頁&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客倉庫&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff01; &…

Day12(回溯法)——LeetCode51.N皇后39.組合總和

1 前言 今天刷了三道回溯法和一道每日推薦&#xff0c;三道回溯法也迷迷糊糊的&#xff0c;每日推薦把自己繞進去了&#xff0c;雖然是一道之前做過的題的變種。刷的腦子疼。。。今天挑兩道回溯題寫一下吧&#xff0c;其中有一道是之前做過的N皇后&#xff0c;今天在詳細寫一寫…

初階數據結構:二叉搜索樹

目錄 概念 性能 效率分析 二分缺陷 功能 插入 查找 刪除 實現 應用 概念 二叉搜索樹&#xff08;又稱&#xff1a;二叉排序樹&#xff09;&#xff0c;是由一些具有特別性質的二叉樹衍變而來。 只要一棵二叉樹具備以下性質&#xff0c;即可稱作二叉搜索樹。 【1】若…

詳解springcloud gateway工作原理、斷言、filter、uri、id、全局跨域、globalfilter等以及關鍵源碼實現

1.gateway概念 網關就是當前微服務項目的"統一入口"程序中的網關就是當前微服務項目對外界開放的統一入口所有外界的請求都需要先經過網關才能訪問到我們的程序提供了統一入口之后,方便對所有請求進行統一的檢查和管理 2. 網關的主要功能 將所有請求統一經過網關網…

C#中的弱引用使用

弱引用&#xff08;Weak Reference&#xff09;是一種特殊的引用類型&#xff0c;它允許你引用一個對象&#xff0c;但不會阻止該對象被垃圾回收器&#xff08;GC&#xff09;回收。弱引用通常用于需要緩存或跟蹤對象&#xff0c;但又不希望因保留引用而導致內存泄漏的場景。弱…

spring響應式編程系列:異步生產數據

目錄 示例 大致流程 create new MonoCreate subscribe new LambdaMonoSubscriber monoCreate.subscribe accept success onNext 時序圖 類圖 數據發布者 MonoCreate 數據訂閱者 LambdaMonoSubscriber 訂閱的消息體 DefaultMonoSink 本篇文章我們來研究如何將…

MCP Python SDK構建的**SQLite瀏覽器**的完整操作指南

以下是使用MCP Python SDK構建的SQLite瀏覽器的完整操作指南&#xff1a; 一、環境準備 安裝依賴 # 安裝MCP SDK及SQLite支持 pip install mcp sqlite3創建測試數據庫 sqlite3 test.db <<EOF CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT); IN…

【Python爬蟲基礎篇】--3.cookie和session

目錄 1.cookie 1.1.定義 1.2.參數 1.3.分類 2.session 3.使用cookie登錄微博 4.使用session登錄 1.cookie 由于http是一個無狀態的協議&#xff0c;請求與請求之間無法相互傳遞或者記錄一些信息&#xff0c;cookie和session正是為了解決這個問題而產生。 例子&#xff1…

風車郵箱系統詳細使用指南:Windows與Ubuntu雙平臺解析

風車郵箱系統V1.2使用手冊 風車郵箱系統詳細使用指南&#xff1a;Windows與Ubuntu雙平臺解析 前言 在日常網絡活動中&#xff0c;我們經常需要一個臨時郵箱來注冊各類網站或接收驗證碼&#xff0c;但不想使用自己的真實郵箱。「風車無線郵箱系統」作為一款優秀的臨時郵箱工具…

同樣的接口用postman/apifox能跑通,用jmeter跑就報錯500

之前沒用過jmeter,第一次用調試壓測腳本遇到了問題 一樣的接口用postman能跑通&#xff0c;用jmeter跑就報錯500&#xff0c;百度很多文章都說是該接口需要加一個‘內容編碼’改成utf-8,我加了還是不行 后來我就想到apifox好像有隱藏的header&#xff0c;然后開始比較apifox的…