1. 程式人生 > >C++ const 引用 指標答疑

C++ const 引用 指標答疑

常變數 const int a

常引用 const int &a

常指標 const int *a

const * int a

用法1:常量
    取代了C中的巨集定義,宣告時必須進行初始化(!c++類中則不然)。const限制了常量的使用方式,並沒有描述常量應該如何分配。如果編譯器知道了某const的所有使用,它甚至可以不為該const分配空間。最簡單的常見情況就是常量的值在編譯時已知,而且不需要分配儲存。―《C++ Program Language》
    用const宣告的變數雖然增加了分配空間,但是可以保證型別安全。
    C標準中,const定義的常量是全域性的,C++中視宣告位置而定。

用法2:指標和常量
    使用指標時涉及到兩個物件:該指標本身和被它所指的物件將一個指標的宣告用const“預先固定”將使那個物件而不是使這個指標成為常量要將指標本身而不是被指物件宣告為常量,必須使用宣告運算子*const
    所以出現在 * 之前的const是作為基礎型別的一部分:
char *const cp; //到char的const指標
char const *pc1; //到const char的指標
const char *pc2; //到const char的指標(後兩個宣告是等同的)
    從右向左讀的記憶方式:
cp is a const pointer to char. 故pc不能指向別的字串,但可以修改其指向的字串的內容
pc2 is a pointer to const char. 故*pc2的內容不可以改變,但pc2可以指向別的字串

且注意:允許把非 const 物件的地址賦給指向 const 物件的指標,不允許把一個 const 物件的地址賦給一個普通的、非 const 物件的指標。

用法3:const修飾函式傳入引數
    將函式傳入引數宣告為const,以指明使用這種引數僅僅是為了效率的原因,而不是想讓呼叫函式能夠修改物件的值。同理,將指標引數宣告為const,函式將不修改由這個引數所指的物件。
    通常修飾指標引數和引用引數:
void Fun( const A *in); //修飾指標型傳入引數
void Fun(const A &in); //修飾引用型傳入引數

引用&的作用:例如a=&b,那麼表示a是b的別名,此時a和b的地址相同。在子函式中呼叫時,形參的改變就是實參的改變,不像C中需要用到指標來實現。

子函式呼叫時,並沒有申請一個空間來存放形參b,也不用將實參a的值傳給形參b,因此使程式執行更簡化。

參考自https://blog.csdn.net/tom__chen/article/details/22206459

用法4:修飾函式返回值
    可以阻止使用者修改返回值。返回值也要相應的付給一個常量或常指標。

用法5:const修飾成員函式(c++特性)
const物件只能訪問const成員函式,而非const物件可以訪問任意的成員函式,包括const成員函式;
const物件的成員是不能修改的,而通過指標維護的物件確實可以修改的;
const成員函式不可以修改物件的資料,不管物件是否具有const性質。編譯時以是否修改成員資料為依據進行檢查。

不加引用的話,str則被複制一份,函式中對str的操作實質上是對其複製品的操作,所以即使在函式中修改了str,呼叫層的原str並不會被改變。
加了引用的話,傳入的str即是呼叫層的實際引數,這樣省卻了複製過程,效率會有提高。但如果函式中修改了str,則原str也會改變,因為其實是同一個東西。
有時候為了追求效率,又希望避免改變原來的str,則可在引用的基礎上加const修飾,這樣函式中就不能再修改str的內容(否則會編譯出錯)

用法5:const與指標

int *ptr;
const int *ciptr;
int const *icptr;
int * const cptr;
const int * const cicptr;

上面是關於const與指標結合時的各種情況,這並不只是C++中經常遇到的問題,在C語言中也會有類似的討論,雖然const並不是C語言中的關鍵字。
int * ptr 是指定義一個指向int 型別的指標ptr。
const int *ciptr 是指定義一個指向const int 型別的指標ciptr,這是const 限定的是(* ciptr),也就是對指標解引用,即const限定的就是資料本身,而非指標。所以ciptr是一個指向常int型資料的指標。
int const * icptr其實和上面的const int *ciptr是一致的因為const只是一個限定符,在int前還是後都 沒有影響,他限定的仍然是(*icptr),並不是icptr,也就是icptr也是指向常int型資料的指標,也就是說在icptr這個指標看來,它指向的資料是常數,是不能改變的,但是是否真的不能改變,需要依據實際的型別的分析,只是不能通過這個指標來改變。也就是說該指標是一個自以為自己指向常量的指標。
int * const cptr 這時候我們還是結合const的位置分析,const限定的是cptr,cptr我們可以知道是一個指標,也就是說const限定的是一個指標,而不是指標指向的資料,也就是說這種定義實質上是定義一個常指標,也就是指標指向的地址是不變的,也就是cptr是不能被賦值的,不能採用這個指標指向其他的物件或者地址。但是這個地址中的資料並不是常數,是可以改變的,可以通過對*cptr進行修改。這種指標實質上也就使得指標的效果大大減小,並不常用。
const int * const cicptr 這種定義結合上面的分析我們知道是一個指向常量的常指標,也就說這個指標指向的地址是一個常地址,指標不能指向其他的物件或者地址。同時對指標cicptr來說,我指向的這個地址中的內容也是不能修改的,是一個常量,是不能修改的,但是該地址的資料能否修改還需要進行實際的分析。

參考自http://www.eepw.com.cn/article/201612/324522.htm

http://www.cnblogs.com/hustcat/archive/2009/04/11/1433549.html