close
C++ 基礎1、引用和指針的區別?

初始化:

引用在定義的時候必須進行初始化,並且不能夠改變

指針在定義的時候不一定要初始化,並且指向的空間可變

訪問邏輯不同:

通過指針訪問對象, 用戶需要使用間接訪問

通過引用訪問對象, 用戶只需使用直接訪問, 編譯器負責將其處理為間接訪問

運算結果不同:

傳指針的實質是傳值,傳遞的值是指針內儲存的變量地址;

傳引用的實質是傳地址,傳遞的是變量的地址。

指針通過下標運算結果是指針所指值為基地址加上偏移, 且基地址可變.

引用通過下標運算結果是引用的是數組才能有這個操作.

自增運算結果不同

`sizeof`運算的結果不同

下標運算:

函數參數:

多級: 有多級指針,但是沒有多級引用,只能有一級引用。

參考: C++ 引用占用內存?- toyijiu的專欄 - CSDN博客

https://blog.csdn.net/toyijiu/article/details/99729949

2、從匯編層去解釋一下引用

參考兩個語句

mov ptr [ebp-4], 1 lea eax, [ebp-4] mov dword ptr [ebp-8], eax ```

a的地址為ebp-4, b的地址為ebp-8, 棧地址由高到底分配.

可以發現這個和指針的複製幾乎一樣,所以引用其實是通過指針來實現的

3、C++中的指針參數傳遞和引用參數傳遞

指針參數傳遞的本質是值傳遞, 傳遞的值是對象的地址, 在調用時形參會在函數棧中開闢空間用於存放傳遞過來的對象的地址,此時形參相當於是實參的副本, 對形參的任何操作都不會反映到實參上, 但是通過形參間接訪問對象的修改是會反應到函數之外的.

引用參數傳遞的本質是傳地址, 傳遞的是實參變量的地址, 首先形參會在函數棧中開闢空間用來存放實參變量的地址, 然後對該形參的任何操作都會被處理未間接尋址,即通過形參中的地址訪問主調函數中的實參變量, 因為通過形參的任何操作都將被應用於主調函數中.

從邏輯上引用相當於對變量起了一個別名, 通過該別名可以對變量進行直接訪問, 由編譯器負責將直接訪問轉換為間接訪問; 而指針訪問變量都是間接訪問.

4、形參與實參的區別?

形參屬於函數內部的局部變量, 在調用函數時才會分配內存, 在函數調用之後會被釋放掉, 因此在函數內部才有效

實參可以使常量, 表達式, 函數等, 無論是何種類型,在函數調用時都必須有一個確定的值,以便把函數的值傳遞給形參

實參和形參的個數一定要嚴格匹配(當然可以忽略有默認值形參), 通常情況下函數類型也是應該嚴格匹配的, 但是允許隱式類型變換,如果類中定義了零參數構造函數,甚至可以使用空初始化列表{}的方式調用零參數構造函數

實參到形參的傳遞是單向的

形參類型為非指針非引用, 則傳遞方式為值傳遞則, 形參為實參的副本, 對形參的任何修改都不會反應在主調函數中

4-2 三種傳遞方式

值傳遞是通過拷貝構造函數實現的

指針傳遞是屬於值傳遞,實參指針向形參傳遞的是對象的地址

引用傳是屬於傳地址, 相當於對變量起了一個別名, 本質上和指針傳遞類似傳遞的都是對象的地址,區別在於對該引用形參的任何操作都會被處理為間接雲芝, 也就是會反應到調用函數中

5、`static`的用法

主要可以分為五個類型: 全局靜態變量, 局部靜態變量, 靜態函數, 靜態成員變量, 靜態成員函數

當定義它的函數或者語句塊結束的時候,作用域結束。

但是當局部靜態變量離開作用域後,並沒有銷毀,而是仍然駐留在內存當中,只不過我們不能再對它進行訪問,直到該函數再次被調用,並且值不變;

在全局變量前加上關鍵字static,全局變量就定義成一個全局靜態變量.

內存中的位置:靜態存儲區,在整個程序運行期間一直存在。

初始化:未經初始化的全局靜態變量會被自動初始化為0(對於自動對象,如果沒有顯示初始化,會調用零參數構造函數,如不存在則編譯失敗);

作用域:全局靜態變量在聲明他的文件之外是不可見的,準確地說是從定義之處開始,到文件結尾。

在局部變量之前加上關鍵字static,局部變量就成為一個局部靜態變量。

內存中的位置:靜態存儲區

初始化:未經初始化的全局靜態變量會被自動初始化為0(對於自動對象,如果沒有顯示初始化,會調用零參數構造函數,如不存在則編譯失敗);

作用域:作用域仍為局部作用域,

局部靜態變量

全局靜態變量

靜態函數

在函數返回類型前加`static`,函數就定義為靜態函數。函數的定義和聲明在默認情況下都是`extern`的,但靜態函數只是在聲明他的文件當中可見,不能被其他文件所用。

函數的實現使用`static`修飾,那麼這個函數只可在本`cpp`內使用,不會同其他`cpp`中的同名函數引起衝突;

`warning`:不要再頭文件中聲明`static`的全局函數,不要在`cpp`內聲明非`static`的全局函數,如果你要在多個`cpp`中復用該函數,就把它的聲明提到頭文件里去,否則`cpp`內部聲明需加上`static`修飾;

類的靜態成員

在類中,靜態成員可以實現多個對象之間的數據共享,並且使用靜態數據成員還不會破壞隱藏的原則,即保證了安全性。

因此,靜態成員是類的所有對象中共享的成員,而不是某個對象的成員。對多個對象來說,靜態數據成員只存儲一處,供所有對象共用

類的靜態函數

靜態成員函數和靜態數據成員一樣,它們都屬於類的靜態成員,它們都不是對象成員。因此,對靜態成員的引用不需要用對象名。

在靜態成員函數的實現中不能直接引用類中說明的非靜態成員,可以引用類中說明的靜態成員(這點非常重要)。*如果靜態成員函數中要引用非靜態成員時,可通過對象來引用。從中可看出,調用靜態成員函數使用如下格式:::();*參數表>靜態成員函數名>類名>

不能被`virtual`修飾,靜態成員函數沒有`this` 指針,虛函數的實現是為每一個對象分配一個`vptr` 指針,而`vptr` 是通過`this` 指針調用的,所以不能為`virtual`;虛函數的調用關係,`this`->`vptr`->`ctable`->`virtual function`

6、靜態變量什麼時候初始化

靜態局部變量和全局變量一樣,數據都存放在全局區域,所以在主程序之前,編譯器已經為其分配好了內存,

但在C 和C++中靜態局部變量的初始化節點又有點不太一樣。

在`C`中,初始化發生在代碼執行之前,編譯階段分配好內存之後,就會進行初始化,所以我們看到==在`C` 語言中無法使用變量對靜態局部變量進行初始化==,在程序運行結束,變量所處的全局內存會被全部回收。

而在`C++`中,初始化時在執行相關代碼時才會進行初始化,主要是由於`C++`引入對象後,要進行初始化必須執行相應構造函數和析構函數,在構造函數或析構函數中經常會需要進行某些程序中需要進行的特定操作,並非簡單地分配內存。所以 `C++`標準規定為全局或靜態對象是有首次用到時才會進行構造 ,並通過`atexit()`來管理。在程序結束,按照構造順序反方向進行逐個析構。所以在 `C++`中是可以使用變量對靜態局部變量進行初始化的。

7、const?

一般可以分為如下六種類型

`const`變量: 表明標了為`const`類型, 通常需要被初始化否則後面將不能被修改, 對該變量的修改操作都會被編譯器阻止.

`const`指針對象: 標明該指針為普通的左值類型可以進行修改, 但是不能通過該變量修改做指向的對象, 則通過該指針只能訪問`const`類型的成員函數.

`const`引用: 它所綁定的對象不能被修改

`const`形參: 和普通的實參分類一樣分為const 變量, const指針對象, const 引用, 作用也類似,表示不能修改該變量.

`const`返回值: 通常是為了表明返回值是一個const類型防止返回值被修改, 或則被當做左值放在賦值運算的左邊

`const`成員函數: 是指成員函數不會修改類對象的任何成員變量, 如果返回值為對象成員的引用則必須返回`const`引用, 同時`const`成員函數不能調用非`const`函數, 其主要是因為`const`成員函數所持有的`this`指針是一個`const`類型的指針, 因為不能調用非`const`類型的成員函數,

參考: c++函數返回類型什麼情況帶const - A_zhu - 博客園https://www.cnblogs.com/Azhu/p/4352613.html

8、`const` 成員函數的理解和應用?

① const Stock & Stock::topval (②const Stock & s) ③const

① 處const:確保返回的Stock 對象在以後的使用中不能被修改

② 處const:確保此方法不修改傳遞的參數s

③ 處const:保證此方法不修改調用它的對象,const 對象只能調用const 成員函數,不能調用非const 函數

9、指針和`const`的用法

當const 修飾指針時,由於const 的位置不同,它的修飾對象會有所不同。

(常指針對象) int const p2` 中`const` 修飾`p2` 的值,所以理解為`p2` 的值不可以改變,即`p2` 只能指向固定的一個變量地址,但可以通過`p2 讀寫這個變量的值。頂層指針表示指針本身是一個常量

(常指針) int const *p1 或者const int *p1 兩種情況中const 修飾p1`,所以理解為`p1 的值不可以改變,即不可以給*p1 賦值改變p1 指向變量的值,但可以通過給p 賦值不同的地址改變這個指針指向。底層指針表示指針所指向的變量是一個常量。

10、`mutable`

如果需要在const 成員方法中修改一個成員變量的值,那麼需要將這個成員變量修飾為mutable。即用`mutable` 修飾的成員變量不受`const` 成員方法的限制;

可以認為mutable 的變量是類的輔助狀態,但是只是起到類的一些方面表述的功能,修改他的內容我們可以認為對象的狀態本身並沒有改變的。實際上由於const_cast的存在,這個概念很多時候用處不是很到了。

通常情況下

`const`成員函數時不能被類對象的成員變量的, 但是可以修改被`mutable`修飾的成員變量

通常我們任務`mutable`位類的輔助狀態, 只是類的一些表訴功能, 修改它不會改變對象的狀態

通常我們可以是用`const_cast`在`const`成員函數中修改所有的成員變量

原文鏈接: https://wangpengcheng.github.io/2019/12/11/interview_c_plusplus/

推薦:

面試常問的 C/C++ 問題,你能答上來幾個?

C++ 面試必問:深入理解虛函數表

很多人搞不清 C++ 中的 delete 和 delete[ ] 的區別

看懂別人的代碼,總得懂點 C++ lambda 表達式吧

Java、C++ 內存模型都不知道,還敢說自己是高級工程師?

C++ std::thread 必須要熟悉的幾個知識點

現代 C++ 並發編程基礎

現代 C++ 智能指針使用入門

c++ thread join 和 detach 到底有什麼區別?

C++ 面試八股文:list、vector、deque 比較

C++經典面試題(最全,面中率最高)

C++ STL deque 容器底層實現原理(深度剖析)

STL vector push_back 和 emplace_back 區別

了解 C++ 多態與虛函數表

C++ 面試被問到的「左值引用和右值引用」

-- END --

進技術交流群,掃碼添加我的微信:Byte-Flow

獲取相關資料和源碼

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()