以前一直在學習C/C++,關於const的使用,這裏出現一點,那裏出現一點。知識用時方恨少,這一段時間正好各類筆試題,其中關於const的用法也是層出不窮,因此疲於在書本上各類翻,這裏彙總一下,加深本身的印象的同時,也方便之後查閱和學習。菜鳥一個,如有錯誤,望指正! 程序員
常類型是指使用類型修飾符const說明的類型,常類型的變量或對象的值是不能被更新的。無論出如今任何上下文都是爲這個目的而服務的。 面試
const修飾符能夠把對象轉變成常數對象,意思就是說利用const進行修飾的變量的值在程序的任意位置將不能再被修改,就如同常數同樣使用!任何修改該變量的嘗試都會致使編譯錯誤: 數組
注意:由於常量在定之後就不能被修改,因此定義時必須初始化: 函數
對於類中的const成員變量必須經過初始化列表進行初始化,以下所示: 學習
在全局做用域裏定義非const變量時,它在整個程序中均可以訪問,咱們能夠把一個非const變量定義在一個文件中,假設已經作了合適的聲明,就能夠在另外的文件中使用這個變量: this
與其餘變量不一樣,除非特別說明,在全局做用域聲明的const變量是定義該對象的文件的局部變量。此變量只存在於那個文件中,不能被其餘文件訪問。經過指定const變量爲extern,就能夠在整個程序中訪問const對象。 spa
注意:非const變量默認爲extern。要使const變量可以在其餘文件中訪問,必須在文件中顯式地指定它爲extern。 3d
const引用是指向const對象的引用: 指針
能夠讀取但不能修改refVal,所以,任何對refVal的賦值都是不合法的。這個限制有其意義:不能直接對ival賦值,所以不能經過使用refVal來修改ival。同理,用ival初始化ref2也是不合法的:ref2是普通的非const引用,所以能夠用來修改ref2指向的對象的值。經過ref2對ival賦值會致使修改const對象的值,爲防止這樣的修改,須要規定將普通的引用綁定到const對象是不合法的。 const 引用能夠初始化爲不一樣類型的對象或者初始化爲右值。如字面值常量: 對象
一樣的初始化對於非const引用倒是不合法的,並且會致使編譯時錯誤。其緣由很是微妙,值得解釋一下。觀察將引用綁定到不一樣的類型時所發生的事情,最容易理解上述行爲。對於下一段代碼:
編譯器會將這些代碼轉換爲一下形式:
咱們發現編譯器會建立一個int型的暫時變量存儲dval,而後將ri綁定到temp上。
注意:引用在內部存放的是一個對象的地址,它是該對象的別名。對於不可尋址的值,如文字常量,以及不一樣類型的對象,編譯器爲了實現引用,必須生成一個臨時對象,引用實際上指向該對象,但用戶不能訪問它。
若是ri不是const,那麼能夠給ri賦一新值。這樣作不會修改dval的,而是修改了temp。指望對ri賦值會修改dval的程序員會發現dval沒有被修改。僅容許const引用綁定到須要臨時使用的值徹底避免了這個問題,直接告訴程序員不能修改,由於const引用是隻讀的哈~(其實就是避免程序員心理預期產生反差。。。)
注意:非const引用只能綁定到與該引用相同類型的對象。 const引用則能夠綁定到不一樣但相關的類型的對象或綁定到右值。
若是咱們在自由存儲區中建立的數組存儲了內置類型的const對象,則必須爲這個數組提供初始化: 由於數組元素都是const對象,沒法賦值。實現這個要求的惟一方法是對數組作值初始化。
C++容許定義類類型的const數組,但該類類型必須提供默認構造函數:
這裏便會調用string類的默認構造函數初始化數組元素。
const限定符和指針結合起來常見的狀況有如下幾種。
C++爲了保證不容許使用指針改變所指的const值這個特性,強制要求這個指針也必須具有const特性:
這裏cptr是一個指向double類型const對象的指針,const先頂了cptr指向的對象的類型,而並不是cptr自己,因此cptr自己並非const。因此定義的時候並不須要對它進行初始,若是須要的話,容許給cptr從新賦值,讓其指向另外一個const對象。但不能經過cptr修改其所指對象的值。
而咱們將一個const對象的地址賦給一個普通的非const指針也會致使編譯錯誤。
不能使用void*指針保存const對象的地址,必須使用const void*類型的指針保存const對象的地址。
下面使人頭暈的一個問題來了----à 容許把非const對象的地址賦給指向const對象的指針,例如:
可是咱們不能經過cptr指針來修改dval的值!!!即便它指向的是非const對象。
而後,咱們必定要知道,不能使用指向const對象的指針修改基礎對象,然而若是該指針指向了非const對象,可用其餘方式修改其所指的對象,因此事實上,能夠修改const指針所指向的值的,可是不能經過const對象指針來進行而已!以下所示:
經過以上,咱們知道指向const對象的指針 確切的講: 自覺得指向const的指針!
C++中還提供了const指針——自己的值不能被修改。
![]()
咱們能夠從右往左把上述定義語句讀做"指向int型對象的const指針"。與其餘const量同樣,const指針的值不能被修改,這意味着不能使curErr指向其餘對象。Const指針也必須在定義的時候初始化。
指針自己是const的試試並無說明是否能用改真真修改其所指向的對象的值。指針對象的值可否修改徹底取決於該對象的類型。
以下能夠這樣定義:
![]()
這樣pi_ptr首先是一個const指針,而後其指向一個const對象~~~
在一個類中,任何不會修改數據成員的函數都應該聲明爲const類型。若是在編寫const成員函數時,不慎修改了數據成員,或者調用了其它非const成員函數,編譯器將指出錯誤,這無疑會提升程序的健壯性。使用const關鍵字進行說明的成員函數,稱爲常成員函數。只有常成員函數纔有資格操做常量或常對象,沒有使用const關鍵字說明的成員函數不能用來操做常對象。常成員函數說明格式以下:
<類型說明符> <函數名> (<參數表>) const;
其中,const是加在函數說明後面的類型修飾符,它是函數類型的一個組成部分,所以,在函數實現部分也要帶const關鍵字。下面舉一例子說明常成員函數的特徵。
既然const是定義爲const函數的組成部分,那麼就能夠經過添加const實現函數重載咯。
其中print成員函數就實現了兩個版本~~~ 重載哦,輸出結果爲 5,52。 const對象默認調用const成員函數。
const修飾函數返回值其實用的並非不少,它的含義和const修飾普通變量以及指針的含義基本相同。以下所示:
通常狀況下,函數的返回值爲某個對象時,若是將其聲明爲const時,多用於操做符的重載。一般,不建議用const修飾函數的返回值類型爲某個對象或對某個對象引用的狀況。緣由以下:若是返回值爲某個對象爲const(const A test = A 實例)或某個對象的引用爲const(const A& test = A實例) ,則返回值具備const屬性,則返回實例只能訪問類A中的公有(保護)數據成員和const成員函數,而且不容許對其進行賦值操做,這在通常狀況下不多用到。
這樣的一個const引用傳遞和最普通的函數按值傳遞的效果是如出一轍的,他禁止對引用的對象的一切修改,惟一不一樣的是按值傳遞會先創建一個類對象的副本, 而後傳遞過去,而它直接傳遞地址,因此這種傳遞比按值傳遞更有效.另外只有引用的const傳遞能夠傳遞一個臨時對象,由於臨時對象都是const屬性, 且是不可見的,他短期存在一個局部域中,因此不能使用指針,只有引用的const傳遞可以捕捉到這個傢伙.
其中關於static、const、static cosnt、const static成員的初始化問題:
在一個類裏創建一個const時,不能給他初值
![]()
類中的static變量是屬於類的,不屬於某個對象,它在整個程序的運行過程當中只有一個副本,所以不能在定義對象時 對變量進行初始化,就是不能用構造函數進行初始化,其正確的初始化方法是:
數據類型 類名::靜態數據成員名=值
最後經過一個完整的例子展現以上結果:
![]()
若是函數須要傳入一個指針,面試官可能會問是否須要爲該指針加上const,把const加在指針不一樣的位置有什麼區別;若是寫的函數須要傳入的參數是一個複雜類型的實例,面試官可能會問傳入值參數或者引用參數有什麼區別,何時須要爲傳入的引用參數加上const。 const是用來聲明一個常量的,當你不想讓一個值被改變時就用const,const int max和int const max 是沒有區別的,均可以。不涉及到指針const很好理解。一旦涉及到指針,則比較容易出問題。
若是const位於星號的左側,則const就是用來修飾指針所指向的變量,即指針指向的對象爲常量;若是const位於星號的右側,const就是修飾指針自己,即指針自己是常量。
所以,[1]和[2]的狀況相同,都是指針所指向的內容爲常量(const放在變量聲明符的位置無關),這種狀況下不容許對內容進行更改操做,如不能*a = 3 ;[3]爲指針自己是常量,而指針所指向的內容不是常量,這種狀況下不能對指針自己進行更改操做,如a++是錯誤的;[4]爲指針自己和指向的內容均爲常量。
若是理解了上面的全部信息,我相信應該問題不大。僅供參考~~~ 但願你們熱烈討論哈。 好了,先寫到這裏,在之後須要補充我再加東西吧。。。敲得手疼~~~ ~!!!