從零開始寫android 的智能指針

Android中定義了兩種智能指針類型,一種是強指針sp(strong pointer),源碼中的位置在system/core/include/utils/StrongPointer.h。另外一種是弱指針(weak pointer)。其實稱之為強引用和弱引用更合適一些。強指針與一般意義的智能指針概念相同,通過引用計數來記錄有多少使用者在使用一個對象,如果所有使用者都放棄了對該對象的引用,則該對象將被自動銷毀。
弱指針也指向一個對象,但是弱指針僅僅記錄該對象的地址,不能通過弱指針來訪問該對象,也就是說不能通過弱指針來調用對象的成員函數或訪問對象的成員變量。要想訪問弱指針所指向的對象,需首先通過wp類所提供的promote()方法將弱指針升級為強指針。弱指針所指向的對象是有可能在其它地方被銷毀的,如果對象已經被銷毀,wp的promote()方法將返回空指針,這樣就能避免出現地址訪問錯的情況。

強弱智能是用來解決什么問題的呢?

1.問題是如何產生的,當我們用new 的時候,如果忘了delet。

#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>using namespace std;class Person{
public:string  name;Person(string n){name =n;cout<<"build person:"<<name<<endl;}void printInfo(){cout<<"i am "<<name<<endl;}~Person(){cout<<"release person:"<<name<<endl;}
};
void test_func(void)
{Person *p = new Person("zhangsan");p->printInfo();
//    Person p = Person("zhangsan");
//    p.printInfo();
}int main(int argc, char **argv)
{int i;for (i = 0; i < 2; i++)test_func();return 0;
}

那么問題產生了。

有內存泄露。

2.開始改進,使用局部變量

?Person *p = new Person("zhangsan");
????p->printInfo();
// ???Person p = Person("zhangsan");
// ???p.printInfo();

? ?析構函數執行,內存泄露沒有了。

結合以上兩點,繼續改進。

3.? 在一個類中包含另一個類的指針,在執行這個類的析構函數時, 刪除另一個類的指針。

#include <iostream>
#include <string.h>using namespace std;class Person{
public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}
};class sp {
private:Person *p;public:sp() : p(0) {}sp(Person *other){cout<<"sp( Person *other)"<<endl;p = other;}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;}~sp(){cout<<"~sp()"<<endl;if (p)delete p;}Person *operator->(){return p;}
};void test_func(sp &other)
{sp s = other;s->printInfo();
}int main(int argc, char **argv)
{sp other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}

?sp出現了。但是還有問題, 在上面的程序中 person被創建了一次,但是被release了兩次。會產生錯誤。

4. 解決思路:引入計數,當是最后一個使用者,銷毀p。

#include <iostream>
#include <string.h>using namespace std;class Person{private:int count=0;
public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}void incStrong(){count +=1;}void decStrong(){count -=1;}int getStrongCount(){return  count;}};class sp {
private:Person *p;public:sp() : p(0) {cout<<"init sp"<<endl;}sp(Person *other){cout<<"sp( Person *other)"<<endl;p = other;p->incStrong();}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;p->incStrong();}~sp(){cout<<"~sp()"<<endl;if (p){p->decStrong();cout<<" ~"<<p->getStrongCount()<<endl;if( p->getStrongCount() ==0){delete p;p=NULL;cout<<"delete p"<<endl;}}}Person *operator->(){cout<<"->"<<endl;return p;}
};void test_func(sp &other)
{sp s = other;s->printInfo();
}int main(int argc, char **argv)
{sp other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}

5. 將計數count 封裝成一個基類。

6.在sp類中,引入模板。

using namespace std;class RefBase{
private:int count;
public:RefBase():count(0){}void incStrong(){count++;}void decStrong(){count--;}int getStrongCount(){return count;}
};class Person:public RefBase{public:Person(){cout<<"build person"<<endl;}~Person(){cout<<"release person"<<endl;}void printInfo(){cout<<"print person"<<endl;}};
template <typename T>
class sp {
private:T *p;public:sp() : p(0) {cout<<"init sp"<<endl;}sp(T *other){cout<<"sp( Person *other)"<<endl;p = other;p->incStrong();}sp(const sp &other){cout<<"sp(const Person *other)"<<endl;p = other.p;p->incStrong();}~sp(){cout<<"~sp()"<<endl;if (p){p->decStrong();cout<<" ~"<<p->getStrongCount()<<endl;if( p->getStrongCount() ==0){delete p;p=NULL;cout<<"delete p"<<endl;}}}T *operator->(){cout<<"->"<<endl;return p;}
};void test_func(sp<Person> &other)
{sp<Person> s = other;s->printInfo();
}int main(int argc, char **argv)
{sp<Person> other = new Person();test_func(other);cout<<"main() end"<<endl;return 0;
}

? ?一個智能指針初見雛形了。

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

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

相關文章

【leetcode hot 100 152】乘積最大子數組

錯誤解法&#xff1a;db[i]表示以i結尾的最大的非空連續&#xff0c;動態規劃&#xff1a;dp[i] Math.max(nums[i], nums[i] * dp[i - 1]); class Solution {public int maxProduct(int[] nums) {int n nums.length;int[] dp new int[n]; // db[i]表示以i結尾的最大的非空連…

圖論整理復習

回溯&#xff1a; 模板&#xff1a; void backtracking(參數) {if (終止條件) {存放結果;return;}for (選擇&#xff1a;本層集合中元素&#xff08;樹中節點孩子的數量就是集合的大小&#xff09;) {處理節點;backtracking(路徑&#xff0c;選擇列表); // 遞歸回溯&#xff…

uniapp離線打包提示未添加videoplayer模塊

uniapp中使用到video標簽&#xff0c;但是離線打包放到安卓工程中&#xff0c;運行到真機中時提示如下&#xff1a; 解決方案&#xff1a; 1、把media-release.aar、weex_videoplayer-release.aar放到工程的libs目錄下; 文檔&#xff1a;https://nativesupport.dcloud.net.cn/…

打包構建替換App名稱

方案適用背景 一套代碼出多個安裝包&#xff0c;且安裝包的應用名稱、圖標都不一樣考慮三語名稱問題 通過 Gradle 腳本實現 gradle.properties 里面定義標識來區分應用&#xff0c;如下文里的 APP_TYPEAAA 、APP_TYPEBBB// 定義 groovy 替換方法 def replaceAppName(String …

DrissionPage移動端自動化:從H5到原生App的跨界測試

一、移動端自動化測試的挑戰與機遇 移動端測試面臨多維度挑戰&#xff1a; 設備碎片化&#xff1a;Android/iOS版本、屏幕分辨率差異 混合應用架構&#xff1a;H5頁面與原生組件的深度耦合 交互復雜性&#xff1a;多點觸控、手勢操作、傳感器模擬 性能監控&#xff1a;內存…

達夢數據庫用函數實現身份證合法校驗

達夢數據庫用函數實現身份證合法校驗 拿走不謝~ CREATE OR REPLACE FUNCTION CHECK_IDCARD(A_SFZ IN VARCHAR2) RETURN VARCHAR2 IS TYPE WEIGHT_TAB IS VARRAY(17) OF NUMBER; TYPE CHECK_TAB IS VARRAY(11) OF CHAR; WEIGHT_FACTOR WEIGHT_TAB : WEIGHT_TAB(7,9,10,5,8,4,…

3dmax的python通過普通的攝像頭動捕表情

1、安裝python 進入cdm&#xff0c;打python要能顯示版本號 >>>&#xff08;進入python提示符模式&#xff09; import sys sys.path顯示python的安裝路徑&#xff0c; 進入到python.exe的路徑 在python目錄中安裝(ctrlz退出python交互模式) 2、pip install mediapipe…

國產Linux統信安裝mysql8教程步驟

系統環境 uname -a Linux FlencherHU-PC 6.12.9-amd64-desktop-rolling #23.01.01.18 SMP PREEMPT_DYNAMIC Fri Jan 10 18:29:31 CST 2025 x86_64 GNU/Linux下載離線安裝包 瀏覽器下載https://downloads.mysql.com/archives/get/p/23/file/mysql-test-8.0.33-linux-glibc2.28…

Vite 權限繞過導致任意文件讀取(CVE-2025-32395)(附腳本)

免責申明: 本文所描述的漏洞及其復現步驟僅供網絡安全研究與教育目的使用。任何人不得將本文提供的信息用于非法目的或未經授權的系統測試。作者不對任何由于使用本文信息而導致的直接或間接損害承擔責任。如涉及侵權,請及時與我們聯系,我們將盡快處理并刪除相關內容。 前言…

poi-tl

官網地址 Poi-tl Documentationword模板引擎https://deepoove.com/poi-tl github 地址 https://github.com/Sayi/poi-tl/tree/master gitcode 加速地址 GitCode - 全球開發者的開源社區,開源代碼托管平臺GitCode是面向全球開發者的開源社區,包括原創博客,開源代碼托管,代碼…

操作系統 4.1-I/O與顯示器

外設工作起來 操作系統讓外設工作的基本原理和過程&#xff0c;具體來說&#xff0c;它概括了以下幾個關鍵步驟&#xff1a; 發出指令&#xff1a;操作系統通過向控制器中的寄存器發送指令來啟動外設的工作。這些指令通常是通過I/O指令&#xff08;如out指令&#xff09;來實現…

琥珀掃描 2.0.5.0 | 文檔處理全能助手,支持掃描、文字提取及表格識別

琥珀掃描是一款功能強大的文檔處理應用程序。它不僅僅支持基本的文檔掃描功能&#xff0c;還涵蓋了文字提取、證件掃描、表格識別等多種實用功能。無論是學生、職員還是教師&#xff0c;都能從中找到適合自己的功能。該應用支持拍照生成電子件&#xff0c;并能自動矯正文檔邊緣…

jQuery UI 小部件方法調用詳解

jQuery UI 小部件方法調用詳解 引言 jQuery UI 是一個基于 jQuery 的用戶界面和交互庫,它提供了一系列小部件,如按鈕、對話框、進度條等,這些小部件極大地豐富了網頁的交互性和用戶體驗。本文將詳細介紹 jQuery UI 中小部件的方法調用,幫助開發者更好地理解和應用這些小部…

浮點數比較在Eigen數學庫中的處理方法

浮點數比較在Eigen數學庫中的處理方法 在Eigen數學庫中進行浮點數比較時&#xff0c;由于浮點數的精度問題&#xff0c;直接使用運算符通常不是推薦的做法。Eigen提供了幾種更安全的方法來進行浮點數比較&#xff1a; 1. 近似相等比較 使用isApprox()函數進行近似比較&#…

Linux-----驅動

一、內核驅動與啟動流程 1. Linux內核驅動 Nor Flash: 可線性訪問&#xff0c;有專門的數據及地址總線&#xff08;與內存訪問方式相同&#xff09;。 Nand Flash: 不可線性訪問&#xff0c;訪問需要控制邏輯&#xff08;軟件&#xff09;。 2. Linux啟動流程 ARM架構: IRAM…

Wincc腳本全部不運行

Wincc腳本全部不運行 前言解決辦法操作步驟 前言 這里主要是指舊項目移植到Wincc的高版本&#xff0c;移植后界面的一些功能均會失效。&#xff08;例如腳本不執行&#xff0c;項目編輯器不可用等情況&#xff09; 解決辦法 Wincc的項目文件中有Dcf文件&#xff0c;Dcf文件包…

使用numpy構建邏輯回歸模型及訓練流程

邏輯回歸模型構建及訓練流程 關于邏輯回歸的數據&#xff0c;有很多學習?的?例樣本。這?我們使?scikit learn提供的數據集?成函數來創建 具體參數可參照官網 Scikit-learn 是? Python 開發的開源機器學習庫&#xff0c;?泛?于數據挖掘和數據分析。 特點&#xff1a;易…

python的多線程和多進程程序編程

CPU密集型使用多進程&#xff0c;IO密集型使用多線程 查看進程ID和線程ID的命令分別是os.getpid()和threading.current_thread() 多進程使用multiprocessing就可以了&#xff0c;通常使用進程池來完成操作&#xff0c;阻塞主進程使用join方法 多線程使用threading模塊&#…

代碼隨想錄算法訓練營第十五天

LeetCode題目: 654. 最大二叉樹617. 合并二叉樹700. 二叉搜索樹中的搜索98. 驗證二叉搜索樹2843. 統計對稱整數的數目 其他: 今日總結 往期打卡 654. 最大二叉樹 跳轉: 654. 最大二叉樹 學習: 代碼隨想錄公開講解 問題: 給定一個不重復的整數數組 nums 。 最大二叉樹 可以用…

[GN] Uart協議解碼器源碼各個方法

系列文章目錄 sigrokdecode 模塊學習指南 — 準備階段 通訊協議 - Uart sigrokdecode 模塊 UART協議解碼器源碼解析 Uart協議解碼器源碼各個方法 文章目錄 系列文章目錄引入庫parity_ok注解類型枚舉options參數annotations 注解annotation_rows 注解分組接收&#xff08;RX&a…