C 關於返回引用和非引用的區別

2021-09-02 20:22:56 字數 2484 閱讀 5040

這幾天剛好遇到乙個題目。我們跳過背景,直接切入正題。

template<

class

t>

class

hypervectoriterator

:public std:

:iterator< std:

:random_access_iterator_tag,

t>

;

這是類的定義,這個類的目的是繼承iterator,然後完成相應的++, --, <, ==等相應符號的過載,作為hypervector類的迭代器。hypervector類是乙個自定義的容器類,支援隨機訪問,這裡先不多介紹此類。下面我們拿自減一的操作符過載來實驗:

// an highlighted block

template<

class

t>

hypervectoriterator<

t> hypervectoriterator<

t>

::operator--()

// an highlighted block

template<

class

t>

hypervectoriterator<

t>

& hypervectoriterator<

t>

::operator--()

幾乎一樣的**,唯一不同的是下面這個類操作符過載返回的是乙個引用。有什麼區別呢?

如果拋開底層彙編**,那麼直觀的理解應該是第乙份**返回物件的時候做了建立物件、物件拷貝、釋放物件的操作,而第二份**返回物件的時候僅做了建立物件一步操作。但不是很能理解的是:函式在結束的時候,應該會釋放函式內的區域性變數的記憶體空間,那麼返回的引用會不會被銷毀?現實是c++使用了那麼多年,如果真發生這樣的bug,應該輪不到被我發現。所以問題應該出自於自己理解的偏差。

我很懶,不是很喜歡翻書。但這個問題一直積壓著又很難受,所以,我嘗試往下再看一層,彙編層。

template<

class

t>

hypervectoriterator<

t> hypervectoriterator<

t>

::operator--()

004193da pop edi

004193db pop esi

004193dc pop ebx

004193dd add esp,

0cch

004193e3 cmp ebp,esp

004193e5 call __rtc_checkesp

(04114c9h)

004193ea mov esp,ebp

004193ec pop ebp

004193ed ret 4

(先補充乙個知識:call指令返回值的時候都是用ax暫存器來儲存的)

返回非引用的時候,004193d7位址的指令果然是做了一次物件的拷貝。而且可以看到儲存到了ebp+8的位址處,ebp應該函式內臨時變數分配的基址,區域性變數儲存的位置應該都比ebp來的小,那麼這個比ebp大的ebp+8位置的地方是**呢?應該是上乙個呼叫者的分配到的記憶體空間。這也很合理,不然在函式退出時區域性變數都被銷毀了還怎麼拿到新分配的物件呢?

再看下面一段**:

template<

class

t>

hypervectoriterator<

t>

& hypervectoriterator<

t>

::operator--()

004193da pop edi

004193db pop esi

004193dc pop ebx

004193dd add esp,

0dch

004193e3 cmp ebp,esp

004193e5 call __rtc_checkesp

(04114c9h)

004193ea mov esp,ebp

004193ec pop ebp

004193ed ret

在004193d5位址執行完call指令後什麼都沒做就進入函式退出前的恢復動作了!也就是返回引用的時候不會改變eax的值。臨時物件一直在暫存器裡面,沒有進入過記憶體。

今天就寫這麼多,第一次寫csdn的文章。這個問題其實是為另乙個問題做鋪墊的,大背景其實是寫自己的迭代器,過載符號函式的時候返回引用還是非引用,會直接影響容器類物件呼叫sort方法時是否產生崩潰。

C 函式返回非引用型別與返回引用型別

函式的返回過程和引數傳遞過程是相對稱的兩個的過程。引數傳遞從呼叫函式向被呼叫函式傳遞,返回值從被呼叫函式向呼叫函式返回。有與傳遞方式的區別 拷貝副本與傳遞本身 函式形參可以分為引用形參和非引用形參 類似的,函式返回值也可以分為非引用型別返回值和引用型別返回值,二者的差異和引用形參和非引用形參型別。當...

C 函式的返回值 返回引用型別 非引用型別

函式的返回主要分為以下幾種情況 1 主函式main的返回值 允許主函式main沒有返回值就可結束 可將主函式main返回的值視為狀態指示器,返回0表示程式執行成功,其他大部分返回值則表示失敗。2 返回非引用型別 3 返回引用型別 當函式執行完畢時,將釋放分配給區域性物件的儲存空間。此時對區域性物件的...

C 函式的返回值 返回引用型別 非引用型別

在海大本科課程設計的 繼承實驗中 matrix 類的成員函式 unsignedchar at int row,int col 獲取第row行第col列的矩陣元素的值 涉及到了返回引用型別的函式返回值 函式的返回主要分為以下幾種情況 1 主函式main的返回值 允許主函式main沒有返回值就可結束 可...