聊聊 C++ 中的幾種智能指針 (上)

一:背景

我們知道 C++ 是手工管理內存的分配和釋放,對應的操作符就是 new/deletenew[] / delete[], ?這給了程序員極大的自由度也給了我們極高的門檻,弄不好就得內存泄露,比如下面的代碼:

void?test()?{int*?i?=?new?int(10);*i?=?10;
}int?main()?{test();
}

這段代碼因為用了 new 而忘了 delete,導致在 nt heap 上分配的 i 隨著棧地址的回收而成了一塊孤懸海外的內存占用,所以修正后的代碼如下:

void?test()?{int*?i?=?new?int(10);*i?=?10;delete?i;
}int?main()?{test();
}

但這種寫法比較麻煩,智者千慮必有一失,總會有忘記加 delete 的時候,那怎么辦呢?大家應該知道內存自動管理有兩種手段。

  1. 引用計數

代表作有 Python,PHP,還有 windows 的句柄管理。

  1. 引用跟蹤

代表作有 C#,JAVA 等一眾工程化語言。

因為 引用計數 實現比較簡單,主要就是記錄下對象的引用次數,次數為 0 則釋放,所以可完全借助 類的構造函數析構函數棧的自動回收特性 弄一個簡單的 引用計數 ,對應著如下四個關鍵詞。

  1. auto_ptr

  2. shared_ptr

  3. unique_ptr

  4. weak_ptr

接下來我們逐個聊一聊。

二:關鍵詞解析

1. auto_ptr

這是 C++ 最早出現一個的 簡單引用計數法,參考代碼如下:

void?test()?{auto_ptr<int>?ptr?=?auto_ptr<int>(new?int(10));
}int?main()?{test();
}

接下來看下匯編代碼:

auto_ptr<int>?ptr?=?auto_ptr<int>(new?int(10));
...
00771D26??call????????std::auto_ptr<int>::auto_ptr<int>?(07710FAh)??
00771D2B??lea?????????ecx,[ebp-0D8h]??
00771D31??call????????std::auto_ptr<int>::~auto_ptr<int>?(0771159h)

可以看到,它分別調用了 構造函數析構函數,接下來找下 auto_ptr 這兩個函數的源碼。

class?auto_ptr?{private:_Ty*?_Myptr;?//?the?wrapped?object?pointerpublic:auto_ptr(auto_ptr_ref<_Ty>?_Right)?noexcept?{_Ty*?_Ptr?=?_Right._Ref;_Right._Ref?=?nullptr;?//?release?old_Myptr?=?_Ptr;?//?reset?this}~auto_ptr()?noexcept?{delete?_Myptr;}
}

源碼一看就明白了,在構造函數中,將 new int 的地址塞給了內部的 _Myptr 指針,在析構函數中對 _Myptr 進行 delete ,真好,這樣就不用整天擔心有沒有加 delete 啦。

值得注意的是,現在 C++ 不推薦這個了,而是建議使用新增的:shared_ptr,unique_ptr,weak_ptr, 怎么說呢?auto_ptr 有一個不好處理的問題,就是現實開發中會出現這么個場景,多個 ptr 指向同一個 引用,如下圖:

bd312945729f9c9a41804082254878ac.png

2. auto_ptr 多引用問題

  1. 方式1:

定義三個 ptr,然后包裝同一個 new int 地址,參考代碼如下:

void?test()?{int*?i?=?new?int(10);auto_ptr<int>?ptr1(i);auto_ptr<int>?ptr2(i);auto_ptr<int>?ptr3(i);
}

這種寫法有沒有問題呢?肯定有問題啦,還記得 auto_ptr 的析構是 delete 嗎?對同一塊內存多次 delete 會拋異常的,如下圖所示:

eddfde7361223bce7be140c6cdd221ae.png
  1. 方式2:

既然定義三個有問題, 那就用賦值運算符= 讓 ptr1,ptr2,ptr3 指向同一個地址是不是就可以啦?參考代碼如下:

void?test()?{int*?i?=?new?int(10);auto_ptr<int>?ptr1(i);auto_ptr<int>?ptr2?=?ptr1;auto_ptr<int>?ptr3?=?ptr2;
}int?main()?{test();
}

那這段代碼有沒有問題呢?有沒有問題得要看 = 運算符是如何重寫的😪,扒一下源碼看看。

template?<class?_Other>
auto_ptr&?operator=(auto_ptr<_Other>&?_Right)?noexcept?{reset(_Right.release());return?*this;
}
_Ty*?release()?noexcept?{_Ty*?_Tmp?=?_Myptr;_Myptr?=?nullptr;return?_Tmp;
}

從源碼看有一個很惡心的點,他會將 _Right 下的 _Myptr 設為 nullptr,也就是說此時的 ptr1 報廢了,言外之意就是后續再訪問 ptr1 會拋 訪問違例

13e75b6539acdf666452d28a36777fea.png

哈哈,C++里面的專業術語叫 控制權轉移

好了,本篇就說這么多吧,下一篇聊聊新增的這些關鍵詞,看看如何將 auto_ptr 更合理的分權。

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

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

相關文章

【Android 學習】深入理解Handler機制

版權聲明&#xff1a;本文為博主原創文章&#xff0c;轉載請注明出處http://blog.csdn.net/u013132758。 https://blog.csdn.net/u013132758/article/details/51355051 Android 提供了Handler和Looper來來滿足線程間的通信&#xff0c;而前面我們所說的IPC指的是進程間的通信。…

第五天個人總結

1.昨天做了什么 頁面完善 2.今天要做什么 暫未知轉載于:https://www.cnblogs.com/sunshine-z/p/8298895.html

【QGIS入門實戰精品教程】4.3:QGIS屬性表按字段鏈接外部屬性數據

屬性數據是GIS空格數據的重要組成部分。屬性數據采集的基本操作由于地理實體(如建筑物) 位于地塊之內成者與地塊有關(如道路),因此,描述地理實體的屬性數據和描述地塊實體與地理實體之間關系的屬性數強大多數都是土地信息的范疇土地空間數據庫的屬性教據主要是用來描述空間目…

解決 Cmder 的光標跟文字有個間距 及常用配置

具體的方法&#xff1a; 菜單 > SettingStartup > Environment set PATH%ConEmuBaseDir%\Scripts;%PATH% set LANGzh_CN.UTF8 chcp 65001 如果無效&#xff1a;在 Cmder 下的 verndor 目錄里&#xff0c;修改 clink.lua 文件大約40和46行&#xff0c;把符號 λ 改為 # …

32 commons-lang包學習

maven依賴 <dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency>一、DateUtils類1、日期比較 public static boolean isSameDay(Date date1, Date date2)&…

做一個高德地圖的 iOS / Android .NET MAUI 控件系列 - 創建控件

我們知道 MAUI 是開發跨平臺應用的解決方案 &#xff0c;用 C# 可以直接把 iOS , Android , Windows , macOS , Linux ,Tizen 等應用開發出來。那我們在這個框架除了用底層自定義的 UI 控件外&#xff0c;如果我們要用如高德地圖這樣的第三方控件&#xff0c;要如何做呢&#x…

flask中的session,render_template()第二和參數是字典

1. 設置一個secret_key 2.驗證登入后加上session,這是最簡單,不保險 . 3.注意render_template傳的參數是字典 轉載于:https://www.cnblogs.com/cuzz/p/8087844.html

統一設置網站html文件輸出編碼為utf-8,以解決亂碼問題

如果設置整站&#xff0c;就在根目錄web.config設置如下參數&#xff0c;如果是指定目錄&#xff0c;在該目錄下的web.config文件設置如下參數&#xff0c;如果沒有web.config文件&#xff0c;可以直接新建一個&#xff1a; <?xml version"1.0" encoding"…

失敗記錄兩則

一&#xff0c;未找出為什么有的CPU應用超高&#xff0c;而另一些CPU靜靜啥也不干。可能是將JOB的優先級設置低了&#xff1f; 二&#xff0c;給BOSS的三星I9300線刷港版ROM失敗。可能文件壞&#xff0c;最可能數據線不是原裝&#xff1f;

【QGIS入門實戰精品教程】1.1:QGIS與GIS的區別和聯系

「劉一哥GIS」系列專欄《QGIS入門實戰精品教程(配套案例數據)》目錄 1. QGIS概述 QGIS(在2.0版本之前稱之為Quantum GIS)于2002年由Gary Sherman創立,在2007年由OSGeo接管,并于2009年發布了1.0版本,目前最高版本為3.22。QGIS采用開源證書GNU GPLv2 (GNU General Public…

簡單的對拍

在算法競賽中&#xff0c;我們常用對拍來初步檢驗程序。 網上也有其它的關于對拍的教程&#xff0c;但是任性的我還是要自己寫一篇教程。  首先&#xff0c;我們要知道我們是用一個叫做” 批處理文件&#xff08;.bat&#xff09;“的東西來處理這個問題。點擊初步了解bat 不過…

AI 之 OpenCvSharp 大圖找小圖(案例版)

要說跟AI扯上啥關系&#xff0c;估計只有庫本身了&#xff0c;但是&#xff0c;這個大圖搜小圖功能還是不錯的&#xff0c;有喜歡的可以試試。我主要用的場景是&#xff0c;具體的某個界面為大圖&#xff0c;界面的某個圖標為小圖&#xff0c;或者&#xff0c;整個桌面為大圖&a…

SaaS應用的十二要素

簡介 如今&#xff0c;軟件通常會作為一種服務來交付&#xff0c;它們被稱為網絡應用程序&#xff0c;或軟件即服務&#xff08;SaaS&#xff09;。12-Factor 為構建如下的 SaaS 應用提供了方法論&#xff1a; 使用標準化流程自動配置&#xff0c;從而使新的開發者花費最少的…

對話Linus:Linux 25歲啦

作為芬蘭Helsinki大學計算機科學系的學生&#xff0c;Linus Torvalds在1991年編寫了Linux操作系統的原始內核。很快&#xff0c;Linux就發展成為了一個全特征的操作系統&#xff0c;并開始運行在智能手機、服務器和各種設備中。在本次通過e-mail進行的訪談中&#xff0c;Torval…

路由器與交換機區別

路由器與交換機區別 近日&#xff0c;在回答知道網友提問的時候&#xff0c;發現很多朋友不知道路由器與交換機的不同&#xff0c;常常問一些看起來有點可笑的問題。比如路由器同時登陸兩個賬號&#xff0c;所以今天寫下這篇經驗&#xff0c;科普一下路由器的功能和交換機的功能…

【QGIS入門實戰精品教程】1.2:QGIS與ArcGIS的區別和聯系

「劉一哥GIS」系列專欄《QGIS入門實戰精品教程(配套案例數據)》目錄 以下是GISGeography官方給出的兩者之間的27點比較(譯): 官方網址:https://gisgeography.com/qgis-arcgis-differences/ 1.QGIS容納更多的數據格式 ArcGIS沒有支持所有的數據格式,毫無疑問,QGIS在處…

mysql中的增刪改查

顯示數據庫中有的表格 SHOW TABLES增 新建表格 CREATE TABLE urls( id int, url varchar(100), description varchar(100) ) 插入值 INSERT INTO chflvghu_test.user (user, password) VALUES (小紅, qwerty); 插入多條數據 INSERT INTO chflvghu_test.user (user, password) V…

押注.NET 是件好事

作者 | Bryan Costanich譯者 | 明知山策劃 | 褚杏娟作為一個在.NET 上構建了不止一個流行平臺的人&#xff0c;我經常被問到它的相關性&#xff0c;以及它是不是一個值得投入的生態系統。這個問題在舊金山灣區的技術世界里尤為流行&#xff0c;這里的技術潮流就像四季一樣變更交…

8-12 canvas專題-階段練習一(上)

8-12 canvas專題-階段練習一&#xff08;上&#xff09; 1 <!DOCTYPE html>2 <html lang"zh-cn">3 <head>4 <meta charset"UTF-8">5 <title>8-12 課堂演示</title>6 </head>7 <style type"text…

【QGIS入門實戰精品教程】2.2:QGIS軟件的下載與安裝(Windows)

文章目錄 一、QGIS下載二、QGIS安裝?一、QGIS下載 QGIS軟件官網下載地址:https://www.qgis.org/en/site/ 進入官網之后,點擊【Download Now】進入下載頁面: 選擇對應的版本進行下載: 開始下載: