最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C++自制心得——開篇(引用)

2023-08-17 09:41 作者:這年頭起名可真不容易  | 我要投稿

前言:?

本心得只適合給那些擁有C語言基礎(chǔ) (系統(tǒng)的自主學(xué)習(xí)過C語言(以找工作為目標(biāo),學(xué)校老師教的一律視作沒學(xué)),了解一些底層機制,用C實現(xiàn)過一些基本數(shù)據(jù)結(jié)構(gòu) (順序表、鏈表、隊列與棧、初等二叉樹、十大經(jīng)典排序等) ) 的人觀看。如果你不滿足上述條件就不要在這里浪費時間了。

本人在寫專欄上的技術(shù)力并不好,如果你覺得這篇文章在排版上有需要改進的地方可以在評論區(qū)留言并附上具體操作流程。

本人目前是大二在讀生,目前剛開始學(xué)習(xí)C++相關(guān)知識,如果有大佬發(fā)現(xiàn)哪里介紹的不對或者有疏漏歡迎在評論區(qū)留言,我盡量在發(fā)現(xiàn)的第一時間糾正。

好,廢話不多講,我們進入正題。?

引用:

什么是引用

兩種代碼的結(jié)果是一樣的

這就是一個簡單的引用代碼。在C++里,引用本質(zhì)上是指針的pro max plus版(據(jù)說在Java里引用是傳值調(diào)用),所以它有如下特點:

1. 在定義時必須指定是哪個變量的引用(Java可以不給)

2. 創(chuàng)建完成后不可更改指向(Java可以改)

3. 引用與其指向的變量共用一塊空間

4. 對引用的合法更改會同步影響它所指的對象

5. 一個變量可擁有無數(shù)個引用(可以套娃)

Java這作業(yè)抄的真爽

(tips: 關(guān)于第二點,如果能改,C++就和Java一樣再也不需要指針了,我懷疑C++這么設(shè)計就是為了保住指針僅剩的就業(yè)空間)

引用的匯編級代碼實現(xiàn)
指針的匯編級代碼實現(xiàn)

(tips:?在調(diào)試的時候打開反匯編窗口就能看到代碼的匯編層,算是一個很實用的小技巧)

我來簡單講一下這幾條匯編指令的意思:

mov? dword ptr [a], 0? ? ? 把值0放入內(nèi)存地址a維護的空間

lea? eax, [a]? ? ? ? ? ? ? ? ? ? 把內(nèi)存地址a放入寄存器eax

mov? dword ptr [b], eax? 把寄存器eax的值放入內(nèi)存地址b維護的空間

(我其實不用講匯編的,把這兩張圖貼出來就夠了)

引用的常見使用場景

顯然,如果不需要更改指定對象,引用在代碼可讀性與美觀度上比指針好得多,只有像類似鏈表,二叉樹等這一類需要頻繁更改指定對象的情況才需要用到指針。讓我們上點實例:

傳引用的Swap函數(shù)是不是比以前好用了不少?再上一個更復(fù)雜的例子。

test1.c

二叉樹遍歷(C).h

二叉樹遍歷(C).c

這段代碼用于輸出該二叉樹的中序遍歷,在_MidorderTraversal函數(shù)有一個參數(shù)int* curPos,表示此時返回用前序遍歷數(shù)組的待填空位。顯然,以這個函數(shù)的邏輯,我們希望這個參數(shù)獨立存在,不受遞歸調(diào)用的影響。因此這個參數(shù)應(yīng)為全局變量,或者是指針變量,也可以是靜態(tài)變量,上面的代碼用的是第二種?,F(xiàn)在有了引用就可以換一種寫法了。

test2.cpp

二叉樹遍歷(C++).h

二叉樹遍歷(C++).cpp

覺得代碼沒有發(fā)生翻天覆地的變化?那我們再來一個。

test3.c

s_clist.h

s_clist.cpp

這是一個經(jīng)典的單鏈表尾插,有沒有注意到尾插函數(shù)里的二級指針?超討厭(〝▼皿▼),但不得不用,誰叫在頭指針為空的情況下我們要改變頭指針本身,那只能傳頭指針的地址,即二級指針。不過現(xiàn)在,用引用就行了。

test3.c(修改后)

s_clist.h(修改后)

s_clist.cpp(修改后)

就問你,爽不爽?講到這里我突然想開個腔,請看下面的代碼:

這個代碼是不是有點眼熟?沒錯它就是在數(shù)據(jù)結(jié)構(gòu)課上很多老師教的單鏈表寫法(據(jù)說有些數(shù)據(jù)結(jié)構(gòu)的書上也是這么寫的),好多學(xué)生看不懂。當(dāng)然,現(xiàn)在的我們肯定是能看懂的,不就是把struct SClistNode* 重定義為PlistNode,然后函數(shù)傳PlistNode的引用。這和SClistNode*&沒有區(qū)別,干嘛寫的這么別扭?據(jù)某些小道消息稱,出書的人覺得指針已經(jīng)夠難了,再給你一個二級指針不就集體Orz了。所以他們整了一個爛活,把代碼寫成上面的樣子,覺得這樣同學(xué)們就能看懂了,把??看樂了。期待各路大仙在評論區(qū)的發(fā)揮。

引用的一些特性

1. 傳值調(diào)用與傳引用調(diào)用的效率問題

效率差異很明顯

以這段代碼為例,函數(shù)a每次傳參都要拷貝四十萬字節(jié)的數(shù)據(jù),整個函數(shù)調(diào)用了十萬次,也就是說我們整整拷貝了37.25個G的數(shù)據(jù)。與此同時,函數(shù)b每次傳參不拷貝數(shù)據(jù)。顯然,在形參大小較大和函數(shù)頻繁調(diào)用的情況下傳引用調(diào)用比傳值調(diào)用擁有更好的性能優(yōu)勢。

2. 常引用問題

很簡單,沒什么可說的

3. 引用做返回值(不知道函數(shù)棧幀創(chuàng)建和銷毀的同學(xué)建議去了解一下)

這塊的問題很有意思,我會重點講。

對于傳值返回,返回的是變量的值,而不是變量的地址,返回值會有一個臨時空間接收,一般情況下,這個臨時空間會是一個寄存器或者是一個在主調(diào)函數(shù)棧幀與被調(diào)函數(shù)棧幀之間的預(yù)先開好的空間(函數(shù)的形參也會被存在這個夾縫里,后面的題會用到這個小知識)

對于傳引用返回,返回的是變量的地址,而不是變量的值,如果返回的變量已經(jīng)隨著函數(shù)棧幀的銷毀被釋放,那這就成了一個經(jīng)典的野指針問題。

最有意思的部分來了,猜猜看這段代碼的運行結(jié)果。

下一個問題,為什么結(jié)果是這樣的?

對于第一第二行輸出,我們用的是int型變量接收的int&返回值,執(zhí)行賦值操作,盡管int&返回值所在的空間已被釋放,但釋放操作與賦值操作間隔時間過短,那個空間還沒有被其他線程占用,因此空間內(nèi)的值沒有被更改,返回值就被保存在一個穩(wěn)定空間內(nèi)。在這種情況下,除了會爆非法越界警告,沒有任何異常。

對于第三第四行輸出,我們們用的是int&型變量接收的int&返回值,此時我們保存了返回值的地址,接下來執(zhí)行printf操作,前文提到函數(shù)形參會被保存在主調(diào)函數(shù)棧幀與被調(diào)函數(shù)棧幀的夾縫里。在printf函數(shù)準(zhǔn)備形參時,因為其調(diào)用空間沒有觸及返回值所在空間,此時形參值正常,緊接著printf的函數(shù)棧幀開辟,返回值所在空間被占用,返回值被銷毀。從第二次調(diào)用printf函數(shù)開始,因返回值被銷毀,形參值異常,打印在屏幕上的結(jié)果就是隨機值。

這道題就留給各位了,答案扣在評論區(qū)就行。

這種代碼雖然沒什么實際意義,但是講解這種匪夷所思的錯誤示范能讓你對下面這個結(jié)論印象深刻。只有當(dāng)返回值所在的空間不會隨著函數(shù)棧幀的銷毀被釋放,才能使用引用返回。

那引用返回有什么讓人眼前一亮的用途嗎?讓我們來個大的。

test3.cpp

s_clist.h

s_clist.cpp

我剛剛又寫了一個查找和一個修改函數(shù),在C語言里我們需要給查找和修改分別設(shè)計一個接口,但是現(xiàn)在有了引用返回,我們就可以這么玩了。

test3.cpp(修改后)

s_clist.h(修改后)

s_clist.cpp(修改后)

諸位,引用返回爽不爽,還用不用C寫代碼了?

現(xiàn)在總結(jié)一下引用的好處:

傳引用傳參

1. 提高效率

2. 輸出型參數(shù)

傳引用返回

1. 提高效率

2. 修改返回對象

引用講完了,離正餐就不遠(yuǎn)了,目前就剩下一個運算符重載要花點時間,剩下的一筆帶過就行。基礎(chǔ)知識搞定了,就要開始玩類和對象了,難度會再次加碼,同志們還要繼續(xù)努力。

C++自制心得——開篇(引用)的評論 (共 條)

分享到微博請遵守國家法律
当涂县| 曲靖市| 都安| 漳浦县| 乐业县| 闽清县| 吉安市| 进贤县| 文成县| 南宫市| 申扎县| 阿克苏市| 锦州市| 林西县| 禄劝| 台北市| 桑植县| 双峰县| 常德市| 贵阳市| 册亨县| 九寨沟县| 彩票| 通城县| 青岛市| 抚宁县| 当阳市| 咸宁市| 巫山县| 江门市| 荣成市| 邳州市| 广安市| 始兴县| 南城县| 琼中| 大足县| 晋江市| 剑川县| 无棣县| 图们市|