C++學習篇(2)
更多精彩請關注微信公眾號“愛折騰的碼農”,二維碼見下圖。
本篇內容主要是分享指標和引用、c++型別轉換操作符等內容,我主要是也根據《More Effective C++》、《C++ primer》和一些面經進行總結的。
引用(reference)
定義:為另一個變數起了一個另外的名字(可以直接說變數的別名),通過宣告符寫成&refival的形式來定義引用型別,其中ival為宣告的變數名。
對於變數別名的理解
引用變數和被引用變數並沒有共用一塊記憶體,引用變數其實是另外開闢了一塊記憶體;
引用變數開闢的記憶體裡面存放的是被引用變數的地址;
任何對引用變數的操作都會轉換為對解引用的操作,例如:(*refval)代表的就是ival。
引用的注意事項
沒有空引用,即定義必須初始化;
引用總是指向它最初獲得的那個物件,即引用將和它初始值物件一直繫結在一起,無法令引用再繫結其他物件。
常量引用注意:
非常量引用不能繫結在常量上
常量引用既可以繫結在常量上也可以繫結在非常量上
不能通過常量引用去改變被引用的值
引用分類
左值:有名字,可以取地址,非臨時
右值:沒有名字,不能取地址,臨時的(定義方式:型別 && 引用名 = 右值表示式)
本篇重點講一下右值引用,因為這在面試中會經常被問到,比如說c++11特性、右值引用的特點。。。
右值引用
-
-
定義:指代臨時的物件,它們只在當前的語句中有效。
-
目的:1、消除兩個物件之間不必要的拷貝,節省運算儲存資源,提高執行效率(轉移語義);2、能夠更簡潔明確的定義泛型程式設計(完美轉發)。
-
轉移語義:將資源 ( 堆,系統物件等 ) 從一個物件轉移到另一個物件,這樣能夠減少不必要的臨時物件的建立、拷貝以及銷燬,能夠大幅度提高 C++ 應用程式的效能。臨時物件的維護 ( 建立和銷燬 ) 對效能有嚴重影響。
-
完美轉發:在引數傳遞過程中屬性和引數值都不變。
-
std::move:將左值引用轉換為右值引用,實現轉移語義。原理:摺疊引用。
-
接下來就是分析指標和引用的區別。相信學習過c語言的人對指標並不陌生,其實指標就是一種儲存變數地址的變數。因為對於每個變數來說都有自己的地址,而指標就是儲存這個地址的變數。
具體指標和引用區別如下,這裡面我只是舉了一些常見的內容,還有一些可以自行去網上百度,很多講的特別詳細。
引用不需要解引用就可以直接獲取指向記憶體空間的值,而指標需要解引用;
引用的賦值操作不需要取地址符來賦值,而是通過變數名;但是指標必須通過取地址符來實現;
引用必須要初始化,且指向的地址不能被改變;但是指標就更加靈活,可以初始化為空或者不初始化;
通過sizeof獲取大小不同,指標一般和作業系統位數有關,如32位的指標佔4個位元組,但是引用是引用物件所佔的大小;
引用和指標自增結果不同;
引用的底層是通過指標實現的;
通過malloc/new申請記憶體的返回值是指標。
C++強制型別轉換
下面說這一段其實主要是為了引出四種型別操作符,可看可不看,不過z在面試中可以簡單介紹一下為什麼會出現這四種型別操作符。
對於C語言來說,它可能會隱式將一種型別轉換成其他型別(比如說使用malloc分配記憶體時,其首先返回void*,然後隱式轉換成相應型別的指標),但是這種轉換並不能夠精確的指明意圖。雖然其也提供了一些方式來進行顯示的轉換,比如說使用一對小括號加上一個物件名稱(標誌符)組成,如
float fnum = 1.2;
int num = (int)fnum; //從float轉換成int
由於小括號和物件名稱在C++中任何地方都可能被用到,因此為了解決這些問題,C++引入了4種新的型別轉換操作符,如下圖所示。
-
static_cast
格式:static_cast<type>(expression)
int firstNumber, secondNumber;
...
double result = static_cast<double>(firstNumber/ secondNumber)
用途
用於基本資料型別之間的轉換,如把int轉換成double
用於類型別轉換,如派生類和基類之間,但是需要注意這種沒有型別安全檢查,即基類轉換成派生類可能會有問題。
把空指標轉換成目標型別的指標
注意
static_cast基本上擁有C就是轉型相同的威力和意義,以及相同的限制。例如,不能夠利用static_cast將一個struct轉換成int,或將一個double轉換成指標;另外,static_cast也不能去除表示式的常量性。因為有一個新式轉型操作符const_cast專司此職。
《More Effective C++》
為什麼要用static_cast轉換而不用c語言中的轉換?
更安全;
更直接明顯,能夠一眼看出是什麼型別轉換成什麼型別,容易找出程式中的錯誤;
可清楚地辨別程式碼中每個顯式的強制轉換;可讀性更好,容易被解析,且能體現程式設計師的意圖。(可看《More Effective c++》第二節)
-
const_cast
格式:const_cast<type> (expression)
用途
用來改變表示式中的常量性或易變性,即將某個物件的常量性去除掉
注意:const_cast不是用於去除變數的常量性,而是去除指向常數物件的指標或引用的常量性,其去除常量性的物件必須為指標或引用。
-
reinterpret_cast
格式:reinterpret_cast<type> (expression),必須是一個指標、引用、算術型別、函式指標或者成員指標
用途:改變指標或引用的型別、將指標或引用轉換為一個足夠長度的整形、將整型轉換為指標或引用型別。不過最常用的是轉換“函式指標”型別。
注意:使用reinterpret_cast強制轉換過程僅僅是位元位的拷貝,因此需要特別謹慎
-
dynamic_cast
格式:dynamic_cast<type> (expression)
用途
其他三種型別轉換都是編譯時完成的,dynamic_cast是執行時處理的,執行時要進行型別檢查;
不能用於內建的基本資料型別的強制轉換;
dynamic_cast轉換如果成功的話返回的是指向類的指標或引用,轉換失敗的話則會返回NULL或者丟擲異常;
使用dynamic_cast進行轉換的,基類中一定要有虛擬函式,否則編譯不通過,但是static_cast沒有這方面要求。
需要檢測虛擬函式的原因:1、類中存在虛擬函式,就說明它有想要讓基類指標或引用指向派生類物件的情況,此時轉換才有意義;2、執行時型別檢查需要執行時型別資訊儲存在類的虛擬函式表中,只有定義了虛擬函式的類才有虛擬函式表。
來自於網上截圖
總結:對於引用部分,相信看面經的人知道問的機率挺多的,特別是右值引用。在回答的時候可以說一下右值引用和左值引用的區別、右值引用的作用、右值引用中轉移語義和完美轉發實現原理(其實就是摺疊引用),然後據一些例子;另外,對於指標和引用的區別,我覺得可以先說引用為什麼是變數的別名,接下來引出引用為什麼必須要初始化,以及與指標的其他區別;最後,對於c++型別轉換部分,可以分成編譯時處理和執行時完成兩類來講解這四種型別轉換,同時也要記得突出每種轉換操作符的重點以及侷限性,比如說const_cast主要去除常量性等等。以上只是本人的一些思路,具體還是要看個人情況而定。
相關文章
- 跟我學C++中級篇——STL的學習C++
- C++遠征離港篇-學習筆記C++筆記
- 資料結構學習(C++)——遞迴【2】(2) (轉)資料結構C++遞迴
- 學習C++C++
- c++學習C++
- javaScript學習基礎篇(2)(彈框,日期)JavaScript
- cocos2d-x學習篇之網路(http)篇HTTP
- C++基礎學習2-資料型別C++資料型別
- C++學習筆記基礎篇15——地址和指標C++筆記指標
- Python學習之專用英語篇(2)Python
- MyBatis學習筆記(2)—對映關係篇MyBatis筆記
- iOS學習筆記-TableView效能優化篇2iOS筆記View優化
- 如何學習C++?C++
- C++ 自我學習C++
- C++學習四C++
- C++學習五C++
- C++學習(49)C++
- C++學習(50)C++
- C++學習(46)C++
- C++學習(47)C++
- C++學習(48)C++
- C++學習安排C++
- c/c++ 學習C++
- C++ Prime 學習C++
- C++學習步驟(C++該如何學)C++
- 資料結構學習(C++)——遞迴【2】(1) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【2】(3) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【2】(4) (轉)資料結構C++遞迴
- 資料結構學習(C++)——遞迴【3】(2) (轉)資料結構C++遞迴
- sass學習篇
- java學習——基礎語法篇(適合已經學過c++的人群)JavaC++
- c++學習總結C++
- c++學習記錄C++
- C++ STL學習——vectorC++
- C++學習筆記C++筆記
- C++ Builder 學習1C++UI
- C/C++學習路線———學習筆記C++筆記
- 資料結構學習(C++)——二叉樹【2】 (轉)資料結構C++二叉樹