【C++初階】四、類和對象(構造函數、析構函數、拷貝構造函數、賦值運算符重載函數)

=========================================================================

相關代碼gitee自取

C語言學習日記: 加油努力 (gitee.com)

?=========================================================================

接上期

【C++初階】三、類和對象
(面向過程、class類、類的訪問限定符和封裝、類的實例化、類對象模型、this指針)
-CSDN博客

?=========================================================================

? ? ? ? ? ? ? ? ? ? ?

引入:類的六個默認成員函數

如果一個類中什么成員都沒有簡稱為空類
但空類中并不是什么都沒有任何類在什么都不寫時
編譯器自動生成以下六個默認成員函數
默認成員函數用戶沒有顯式實現編譯器自動生成成員函數稱為默認成員函數

? ? ? ? ? ? ? ? ? ? ?

  • 初始化和清理
    構造函數(1)?-- 完成成員變量的初始化工作
    析構函數(2) -- 完成一個對象結束生命周期后的資源清理工作
    ? ? ? ? ? ? ??
  • 拷貝復制
    拷貝構造函數(3) -- 使用同類對象初始化創建對象
    賦值重載(4) -- 把一個對象賦值給另一個對象
    ? ? ? ? ? ? ? ??
  • 取地址重載
    主要是普通對象(5)const對象取地址(6),這兩個很少會自己實現

? ? ? ? ? ? ? ? ?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

? ? ? ? ? ? ? ? ? ? ?

一 . 構造函數(難)

構造函數的概念和特性:

? ? ? ? ? ? ? ? ? ?

C++構造函數的概念:

還是假設有以下Date類:
//日期類:
class Date
{
public://我們自己定義的初始化函數:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}//打印日期函數:void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private://私有成員函數:int _year; //年int _month; //月int _day; //日
};int main()
{Date d1;d1.Init(2023, 11, 16);d1.Print();Date d1;d1.Init(2023, 11, 17);d1.Print();return 0;
}
  • 對于以上的Date類,可以通過我們自己定義的 Init共有函數方法給對象設置日期

    如果每次創建對象都需要調用該方法初始化對象成員的話

    有點麻煩而且可能會忘記初始化,那能否在對象創建時就自動進行初始化呢?

    ? ? ? ? ? ? ? ? ? ??
  • C++為了優化C語言需要自己初始化的情況,有了一個新概念構造函數
    構造函數特殊的成員函數其名字類名相同
    創建類類型對象時由編譯器自動調用進行對象的初始化
    保證每個數據成員都有一合適的初始值,并且在對象整個聲明周期內只會調用一次
    ? ? ? ? ? ? ? ? ??
  • 構造函數分為有參構造函數無參構造函數
    我們
    創建對象時可以設置各成員變量初始化的值
    如果
    沒有設置,則對象初始化時會調用無參構造函數
    如果
    設置了,則對象初始化時會調用相應的有參構造函數

Date類 -- 圖示:

? ? ? ? ? ? ? ? ??

主函數通過構造函數創建對象 -- 圖示:

? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ??
---------------------------------------------------------------------------------------------

? ? ? ? ? ? ? ? ? ??

C++構造函數特征:

? ? ? ? ? ? ? ? ? ?

  • 構造函數名名相同構造函數沒有返回值
    對象實例化編譯器自動調用對應的構造函數
    ? ? ? ? ? ? ? ??
  • 如果類中沒有顯式定義構造函數,則C++編譯器自動生成一個無參的默認構造函數
    一旦用戶顯式定義構造函數編譯器將不再自動生成構造函數
    所以如果定義了有參構造函數最好再定義一個無參構造函數
    防止創建對象時需要無參構造函數而又無法調用到
    ? ? ? ? ? ? ? ??
  • 構造函數也是函數可以有參數,所以也可以對其設置缺省參數
    將一個有參構造函數初始化全部成員變量的構造函數
    所有參數都設置一個缺省參數全缺省構造函數),
    這樣該構造函數就既實現了有參構造函數的任務
    又實現了無參構造函數的任務,因為初始化對象時如果不給初始化值
    那么有參構造函數的缺省參數會發揮作用實現無參構造函數的任務
    這樣一個構造函數就可以替代有參無參兩個構造函數
    ? ? ? ? ? ??
  • 構造函數支持重載雖然支持重載
    但如果已經定義了全缺省構造函數已經能夠實現無參構造函數的情況下
    這時如果再定義一個無參構造函數雖然構成了構造函數重載
    但是實際調用時是會出錯的,因為全缺省構造函數無參構造函數功能重復
    編譯器就會不知道該調用哪個構造函數
    ? ? ? ? ? ? ??
  • 無參的構造函數全缺省的構造函數都稱為默認構造函數
    并且默認構造函數只能有一個否則會有調用歧義
    注意:
    無參構造函數全缺省構造函數編譯器默認生成的構造函數
    都可以認為是默認構造函數
    不傳參數還可以被調用的構造函數都可以叫默認構造函數
全缺省構造函數 -- 圖示:

? ? ? ? ? ? ? ? ? ? ? ? ? ??

編譯器默認生成的構造函數的作用:
  • C++中把類型分成了內置類型基本類型自定義類型
    內置類型就是語言原生的數據類型intdouble指針……);
    自定義類型就是我們使用 class / struct / union 自己定義的類型
    關于編譯器生成的默認構造函數該構造函數會對我們未定義的成員變量進行初始化
    ? ? ? ? ? ? ? ?
  • 不同編譯器初始化方式不同
    VS2013中:
    如果對象的成員變量為內置類型
    默認生成構造函數不會對其進行處理為隨機值);
    如果對象的成員變量為自定義類型
    默認生成構造函數則會調用該自定義類型的默認構造函數
    VS2019情況會更復雜

    如果對象的成員變量全是內置類型
    默認生成構造函數不會對其進行處理為隨機值);
    如果對象的成員變量既有內置類型又有自定義類型
    則會對其中的內置類型進行處理int類型成員變量會被初始化為0),
    對其中的自定義類型,會調用該自定義類型的默認構造函數
    ? ? ? ? ? ?
  • 所以默認生成的構造函數根據對象的成員變量的情況判斷是否要對其進行處理
    如果對象的成員變量為自定義類型,就調用該自定義類型的默認構造函數
    如果是內置類型,則不進行處理為隨機值
    會處理自定義類型不一定處理內置類型(看編譯器),建議統一當成不會進行處理
圖示:

? ? ? ? ? ?

  • 因此C++11中針對內置類型成員不初始化的缺陷,又打了一個補丁
    內置類型成員變量類中聲明可以給默認值
    給了默認值又有定義顯式構造函數的話顯式構造函數為準
圖示:

? ? ? ? ? ? ? ? ? ? ?

總結:
  • 一般情況下我們都要自己寫構造函數
    ? ? ? ? ? ? ?
  • 成員變量如果都是自定義類型或者成員變量聲明時給了缺省值
    那就可以考慮讓編譯器自己生成構造函數

? ? ? ? ?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

? ? ? ? ? ? ?

二 . 析構函數

析構函數的概念和特性:

? ? ? ? ? ? ? ? ?

C++析構函數的概念:

? ? ? ? ? ??

  • 通過前面對構造函數的了解,我們知道了一個對象是怎么來的
    可一個對象又是怎么沒的呢?如果說構造函數是我們以前寫的Init初始化函數

    那么析構函數就是我們以前寫的Destroy銷毀函數
    ? ? ? ? ? ? ? ? ? ? ? ??

  • 析構函數構造函數功能相反析構函數不是完成對對象本身的銷毀
    局部對象銷毀工作是由編譯器完成
    對象銷毀時會自動調用析構函數完成對象中資源的清理工作

? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ??
---------------------------------------------------------------------------------------------

? ? ? ? ? ? ? ? ? ??

C++析構函數的特性:

? ? ? ? ? ? ? ??

  • 析構函數名 = 在類名前加上字符 ~” (按位取反符號
    ? ? ? ? ? ? ? ? ? ??
  • 析構函數沒有返回值函數參數
    ? ? ? ? ? ??
  • 一個類只能有一個析構函數沒有顯式定義編譯器自動生成默認的析構函數
    析構函數不支持重載
    ? ? ? ? ? ? ? ? ??
  • 對象聲明周期結束C++編譯系統自動調用析構函數

析構函數 -- 圖示:

? ? ? ? ? ? ? ? ? ? ? ? ? ??

編譯器默認生成的構造函數的作用:
  • 默認生成的析構函數其行為跟構造函數的類似
    針對內置類型的成員變量析構函數不會對其進行處理
    針對自定義類型的成員變量析構函數也會調用該自定義類型的默認析構函數
    ? ? ? ? ? ? ? ? ? ?
  • 如果類中沒有申請資源析構函數可以不寫直接使用編譯器生成的默認析構函數
    比如之前寫的Date日期類就可以不寫
    而如果類中有申請資源則一定要寫析構函數否則會導致資源內存泄漏
    比如Stack棧類需要顯式定義析構函數進行資源清理
圖示:

? ? ? ? ?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

? ? ? ? ? ? ?

三 . 拷貝構造函數(難)

拷貝構造函數的概念和特性:

? ? ? ? ? ? ? ??

C++拷貝構造函數的概念:

? ? ? ? ? ? ? ? ? ? ?

  • 拷貝構造函數
    只有單個形參該形參對本類類型對象的引用一般常用const修飾),
    在使用已存在的類類型對象拷貝創建新對象時編譯器自動調用

圖示:

? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ??
---------------------------------------------------------------------------------------------

? ? ? ? ? ? ? ? ? ??

C++拷貝構造函數的特性:

? ? ? ? ? ? ? ? ? ? ? ?

  • 拷貝構造函數也是特殊的成員函數構造函數的一個重載形式
    ? ? ? ? ? ? ? ? ?
  • 拷貝構造函數的參數只有一個必須是類類型對象的引用
    使用傳值方式作為其參數編譯器會直接崩潰因為會引發無窮遞歸調用
    ? ? ? ? ? ? ? ? ? ? ? ?
  • 如果沒有顯式定義拷貝構造函數編譯器會生成默認的拷貝構造函數
    默認的拷貝構造函數拷貝對象時會按內存存儲按字節序完成拷貝
    這種拷貝叫做淺拷貝或者值拷貝
注:

在編譯器生成的默認拷貝構造函數內置類型按照字節方式直接拷貝值拷貝),
自定義類型則會調用該自定義類型的拷貝構造函數完成拷貝

圖示:

? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ??

  • 編譯器生成的默認拷貝構造函數已經可以完成字節序的值的拷貝值拷貝
    當類中沒有涉及資源申請申請動態空間等
    淺拷貝已經足夠使用是否顯式定義拷貝構造函數都可以
    但是一旦涉及到了資源申請拷貝構造函數一定要顯式定義進行深拷貝
???????圖示:

? ? ? ? ? ? ? ? ? ?

  • 拷貝構造函數典型調用場景
    使用已存在的對象拷貝創建新對象函數參數類型類類型對象
    函數返回值類型類類型對象
注:

為了提高效率一般對象傳參盡量使用引用類型返回
返回時根據實際場景能用引用返回盡量使用引用返回

? ? ? ? ?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

? ? ? ? ? ? ?

四 . 賦值運算符重載

運算符重載的使用和注意事項

? ? ? ? ? ? ? ? ? ?

引言:

對于內置類型intdouble……)數據我們可以直接對其使用運算符
假設我們有整型變量ab,我們可以對其使用
???????a == b判斷相等)?、a > b判斷大小),
但對自定義類型的數據而言,就不能直接對其使用運算符
因為編譯器不知道怎么判斷我們自定義的類型,所以需要我們自己定義其判斷的規則

圖示 --? 自定義類型判斷規則:

? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ??
---------------------------------------------------------------------------------------------

? ? ? ? ? ? ? ? ? ??

運算符重載的使用:

  • C++為了增強代碼的可讀性引入了運算符重載運算符重載具有特殊函數名的函數
    ???????也具有其返回值類型函數名字以及參數列表
    返回值類型參數列表和普通的函數類似
    ? ? ? ? ? ? ? ??
  • 函數名字關鍵字operator后接需要重載的運算符符號
    加法運算符重載? --? operator+)?
    ? ? ? ? ? ? ? ? ??
  • 函數原型返回值類型 operator操作符(參數列表)

圖示 --? 類外運算符重載:

? ? ? ? ? ? ? ? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ??
---------------------------------------------------------------------------------------------

? ? ? ? ? ? ? ? ? ??

運算符重載的注意事項:

  • 不能通過連接其它符號來創建新的操作符:比如operator@
    ? ? ? ? ? ? ??
  • 重載操作符必須有一個類類型參數
    ? ? ? ? ? ? ? ? ? ??
  • 用于內置類型的運算符含義不能改變
    例如內置的整型+ 不能改變其含義 ++= 是不一樣的
    ? ? ? ? ? ? ? ?
  • 重點
    作為類成員函數重載形參看起來比操作數數目少一個
    因為成員函數第一個參數為隱藏的this指針
    ? ? ? ? ? ? ? ??
  • 注意以下五個運算符不能重載
    .* ”? 、?“ :: ”? 、“ sizeof ”? 、“ ?: ”? 、“ . ”?????
圖示 --? 類中運算符重載:

? ? ? ? ? ? ? ? ? ? ??

  • 一個類要重載哪些運算符主要看這個運算符對這個類來說有沒有意義
    有意義可以重載沒有意義不要重載
    日期類來說日期的 +() *() /() 都沒有意義-() 有意義
    兩個日期相減可以計算兩日期相差了多少天
    日期+日期沒有意義日期+整型有意義
    d1 + 100 計算d1日期的100天后的日期
圖示 --? 類中實現 += 和 + 運算符重載:

:“+=運算符重載中要設置返回值 -- return *this ,這里忘了寫了
? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ?


? ? ? ? ? ? ? ? ? ??

賦值運算符(=)重載

? ? ? ? ? ? ? ??

賦值運算符 -- "=" ,賦值運算符重載就是讓自定義類型也能像內置類型一樣使用=

? ? ? ? ? ? ? ?

賦值運算符重載格式:

  • 參數類型const T&
    const修飾參數,能夠防止賦值拷貝時左右值寫反了,導致改變了原對象
    T& 傳參引用接收右值的別名”,提高傳參效率
    ? ? ? ? ? ? ? ? ????????
  • 返回值類型T&
    引用返回可以提高返回的效率設置返回值還為了支持=連續賦值
    ? ? ? ? ? ? ? ? ?
  • 定義賦值運算符重載函數時需要檢測是不是自己給自己賦值的情況
    ? ? ? ? ? ? ? ? ? ? ?
  • 最終返回*this(即返回被賦值對象本身),能夠符合=連續賦值的含義
    ? ? ? ? ? ? ?
  • 用戶沒有顯式實現編譯器生成一個默認的賦值運算符重載函數
    行為拷貝構造函數類似
    針對內置類型成員變量:進行 值拷貝淺拷貝
    針對自定義類型成員變量:會調用該自定義類型的 賦值運算符重載函數
    注意:
    如果類中
    沒有資源”(Date類),賦值運算符重載函數要不要顯式定義都可以
    如果類中資源”(Stack類),賦值運算符重載函數必須要顯式定義
    ? ? ? ? ? ? ? ? ? ? ??
  • 賦值運算符只能重載成類的成員函數只能在類中定義重載),不能重載為全局函數
    原因

    賦值運算符重載函數如果不顯式實現編譯器生成一個默認的
    此時如果再在類外實現一個全局的賦值運算符重載函數
    就會和編譯器在類中生成的默認賦值運算符重載函數沖突
    ???????所以賦值運算符重載函數只能是類的成員函數

圖示 -- 以Date類為例:

?????

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

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

相關文章

如何使用springboot服務端接口公網遠程調試——實現HTTP服務監聽

&#x1f308;個人主頁&#xff1a;聆風吟 &#x1f525;系列專欄&#xff1a;網絡奇遇記、Cpolar雜談 &#x1f516;少年有夢不應止于心動&#xff0c;更要付諸行動。 文章目錄 &#x1f4cb;前言一. 本地環境搭建1.1 環境參數1.2 搭建springboot服務項目 二. 內網穿透2.1 安裝…

ATA-2042高壓放大器在細胞的剪切應力傳感器研究中的應用

微流控技術是一種通過微小的通道和微型裝置對流體進行精確操控和分析的技術。它是現代醫學技術發展過程中的一種重要的生物醫學工程技術&#xff0c;具有廣泛的應用前景和重要性。它在高通量分析、個性化醫療、細胞篩選等方面有著巨大的潛力&#xff0c;Aigtek安泰電子今天就將…

.Net面試題4

1.請解釋一下泛型&#xff08;Generics&#xff09;在C#中的作用。 泛型是一種將數據類型參數化的機制&#xff0c;使得代碼可以在編譯時具有更強的類型安全性和靈活性。C#中的泛型可以用于類、接口、方法等的定義和實例化。泛型允許在編寫代碼時使用具有不同實參的類型&#x…

HR8833 雙通道H橋電機驅動芯片

HR8833為玩具、打印機和其它電機一T化應用提供一種雙通道電機驅動方案。HR8833提供兩種封裝&#xff0c;一種是帶有L露焊盤的TSSOP-16封裝&#xff0c;能改進散熱性能&#xff0c;且是無鉛產品&#xff0c;引腳框采用100&#xff05;無錫電鍍。另一種封裝為SOP16&#xff0c;不…

智駕芯片全矩陣「曝光」,這家企業的車載品牌正式官宣

隨著汽車智能化加速&#xff0c;智能駕駛芯片格局逐漸清晰。 針對L0-L2&#xff0c;業內基本采用智能前視一體機方案&#xff1b;要實現高速NOA、城市NOA等更為高階的智駕功能等&#xff0c;則基本采用域控制器方案。從前視一體機至域控&#xff0c;再逐步演進到艙駕一體、中央…

python基于DETR(DEtection TRansformer)開發構建鋼鐵產業產品智能自動化檢測識別系統

在前文中我們基于經典的YOLOv5開發構建了鋼鐵產業產品智能自動化檢測識別系統&#xff0c;這里本文的主要目的是想要實踐應用DETR這一端到端的檢測模型來開發構建鋼鐵產業產品智能自動化檢測識別系統。 DETR (DEtection TRansformer) 是一種基于Transformer架構的端到端目標檢…

springboot項目修改項目名稱

參考該文章正確修改項目名稱&#xff1a;SpringBoot項目怎么重命名_springboot修改項目名稱-CSDN博客

【Lodash】 Filter 與Map 的結合使用

用Filter過濾數據之后&#xff0c;想給某個字段重新賦值 在使用 filter() 方法過濾數據后&#xff0c;如果你想給某個字段賦值&#xff0c;你可以使用 map() 方法來修改數組中的元素。map() 方法可以對數組中的每個元素應用一個函數&#xff0c;并返回一個新的數組。 以下是一…

【Django使用】10大章31模塊md文檔,第5篇:Django模板和數據庫使用

當你考慮開發現代化、高效且可擴展的網站和Web應用時&#xff0c;Django是一個強大的選擇。Django是一個流行的開源Python Web框架&#xff0c;它提供了一個堅實的基礎&#xff0c;幫助開發者快速構建功能豐富且高度定制的Web應用 全套Django筆記直接地址&#xff1a; 請移步這…

外匯天眼:多名投資者賬戶被惡意清空,遠離volofinance!

最近&#xff0c;外匯平臺volofinance因有多名投資者投訴&#xff0c;“榮幸”成為外匯天眼黑平臺榜單中的一員&#xff0c;那么volofinance到底做了什么導致投資者前來投訴曝光呢&#xff1f; 起底volofinace 在網絡搜索中&#xff0c;關于volofinance的信息少之又少&#xf…

成為AI產品經理——模型評估指標

目錄 一、模型評估分類 1.在線評估 2.離線評估 二、離線模型評估 1.特征評估 ① 特征自身穩定性 ② 特征來源穩定性 ③ 特征成本 2.模型評估 ① 統計性評估 覆蓋度 最大值、最小值 分布形態 ② 模型性能指標 分類問題 回歸問題 ③ 模型的穩定性 模型評估指標分…

配置mvn打包參數,不同環境使用不同的配置文件

方法一&#xff1a; 首先在/resource目錄下創建各自環境的配置 要在不同的環境中使用不同的配置文件進行Maven打包&#xff0c;可以使用Maven的profiles特性和資源過濾功能。下面是配置Maven打包參數的步驟&#xff1a; 在項目的pom.xml文件中&#xff0c;添加profiles配置…

python 負數 處理

num_negative -4 print(num_negative) num_dec_to_hex hex(num_negative) print(負數轉十六進制&#xff1a; num_dec_to_hex) /---------------------------------------------------------/ -4 負數轉十六進制&#xff1a;-0x4通過上面代碼片段可以看到&#xff0c;python…

第一個Mybatis項目

&#xff08;一&#xff09;為什么要用Mybatis? &#xff08;1&#xff09;Mybatis對比JDBC而言&#xff0c;sql&#xff08;單獨寫在xml的配置文件中&#xff09;和java編碼分開&#xff0c;功能邊界清晰&#xff0c;一個專注業務&#xff0c;一個專注數據。 &#xff08;2&…

【C++】:多態

朋友們、伙計們&#xff0c;我們又見面了&#xff0c;本期來給大家解讀一下有關多態的知識點&#xff0c;如果看完之后對你有一定的啟發&#xff0c;那么請留下你的三連&#xff0c;祝大家心想事成&#xff01; C 語 言 專 欄&#xff1a;C語言&#xff1a;從入門到精通 數據結…

Linux(CentOS7)上安裝mysql

在CentOS中默認安裝有MariaDB&#xff08;MySQL的一個分支&#xff09;&#xff0c;可先移除/卸載MariaDB。 yum remove mariadb // 查看是否存在mariadb rpm -qa|grep -i mariadb // 卸載 mariadb rpm -e --nodeps rpm -qa|grep mariadb yum安裝 下載rpm // 5.6版本 wge…

XML映射文件

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace"org.mybatis.example.BlogMapper&q…

conan 入門(三十二):package_info中配置禁用CMakeDeps生成使用項目自己生成的config.cmake

conanfile.py中定義的package_info()方法用于向package的調用者(conumer)提供包庫名&#xff0c;編譯/連接選項&#xff0c;文件夾等等信息&#xff0c;有了這些信息構建工具的generator就可以根據它們生成對應的文件&#xff0c;用于調用者引用package. 比如基于cmake的CMakeD…

線索二叉樹:C++實現

引言&#xff1a; 線索二叉樹是一種特殊的二叉樹&#xff0c;它可以通過線索&#xff08;線索是指在二叉樹中將空指針改為指向前驅或后繼的指針&#xff09;的方式將二叉樹轉化為一個線性結構&#xff0c;從而方便對二叉樹進行遍歷。本文將介紹如何使用C實現線索二叉樹。 技術…

安全地公網訪問樹莓派等設備的服務 內網穿透--frp 23年11月方法

如果想要樹莓派可以被公網訪問&#xff0c;可以選擇直接網上搜內網穿透提供商&#xff0c;一個月大概10塊錢&#xff0c;也有免費的&#xff0c;但是免費的速度就不要希望很好了。 也可以選擇接下來介紹的frp&#xff0c;這種方式不需要付費&#xff0c;但是需要你有一臺有著公…