1、引用、常量引用
引用主要被用做函數的形式參數--通常將類對象傳遞給一個函數.
引用在內部存放的是一個對象的地址,它是該對象的別名。引用不占用內存,因為取地址引用的值和被引用變量的地址相同。但是objdump –d xx底層編譯器實現其實還是指針。
(1)引用必須初始化. 但是用對象的地址初始化引用是錯誤的,我們可以定義一個指針引用.
int ival = 1092; int &re = 1092; //錯誤。非常量引用的初始值必須為左值 int &re = ival; //ok int &re2 = &ival; //錯誤。不可用對象的地址初始化引用 int *pi = &ival; int *&pi2 = pi; //ok。可定義指針引用 int *&pi3 = &ival; //錯誤
(2)一旦引用已經定義,它就不能再指向其他的對象.這就是為什么它要被初始化的原因.
(3)const引用可以用不同類型的對象初始化(只要能從一種類型轉換到另一種類型即可),也可以是不可尋址的值
double dval = 3.14159; //下3行僅對const引用才是合法的,對非const會編譯錯誤 const int &ir = 1024; const int &ir2 = dval; const double &dr = dval + 1.0;
對於不可尋址的值,以及不同類型的對象,編譯器為了實現引用,必須生成一個臨時對象,引用實際上指向該對象,但用戶不能訪問它。所以上面的通過編譯器轉為:
//不可尋址,文字常量 int tmp1 = 1024; const int &ir = tmp1; //不同類型 int tmp2 = dval;//double -> int const int &ir2 = tmp2; //另一種情況,不可尋址 double tmp3 = dval + 1.0; const double &dr = tmp3;
(4)不允許非const引用指向需要臨時對象的對象或值,即,編譯器產生臨時變量的時候引用必須為const(注意)
int iv = 100; int *&pir = &iv;//錯誤,非const引用對需要臨時對象的引用 int *const &pir = &iv;//ok const int ival = 1024; int *&pi_ref = &ival; //錯誤,非const引用是非法的 const int *&pi_ref = &ival; //錯誤,需要臨時變量,且引用的是指針,而pi_ref是一個非常量指針 const int * const &pi_ref = &ival; //正確 //補充 const int *p = &ival; const int *&pi_ref = p; //正確
********對於const int *const & pi_ref = &iva; 具體的分析如下:*********【仍需學習】
1.不允許非const引用指向需要臨時對象的對象或值
int a = 2; int &ref1 = a;// OK.有過渡變量。 const int &ref2 = 2;// OK.編譯器產生臨時變量,需要const引用
2.地址值是不可尋址的值
int * const &ref3 = &a; // OK;
3.於是,用const對象的地址來初始化一個指向指針的引用
const int b = 23; const int *p = &b; const int *& ref4 = p; const int *const & ref5 = &b; //OK
const引用的語義:
試圖通過此引用去(間接)改變其引用的對象的值時,編譯器會報錯。保證不會通過此引用間接的改變被引用的對象,但被引用對象還可通過別的方式改變其值。
與非常量引用區別:常量引用可讀不可改,與綁定對象是否為const無關,可綁定到不同但相關的類型對象或左值。非常量引用可讀可改,只可與非const對象綁定,只能綁定到與該引用同類型的對象。
2、常量指針、指針常量
常量指針:指向常量的指針,能通過常量指針讀取內存中數據,但不可修改內存中數據
聲明:const int * p; int const * p;
注:可以將一個常量的地址賦值給一個對應類型的常量指針,因為常量指針不能夠通過指針修改內粗數據。只能防止通過指針引用修改內存中的數據,並不保護指針所指向的對象。
指針常量:指針本身是常量,其本身不可改變,即指向的位置不可改變,但其指向的內容可改變
聲明:int * const p=&a;
注:指針常量必須在聲明的同時對其初始化,不允許先聲明一個指針常量隨后再對其賦值,這和聲明一般的常量是一樣的
區分兩者:*為界,左定值,右定向。const在*左邊=指針指向的內容不可改變(常量指針),const在*右邊=指針指向的位置不可改變(指針常量)
int a = 1; //定義變量 const int b = 2; //定義常量 const int *ptr1 = &a; //定義常量指針【並不能通過ptr1修改a的值,但a本身不是常量,a本身是可以修改的】 int* const ptr2 = &a; //定義指針常量,必須賦值 int *ptr3 = &b; //錯誤,不能把常量的地址賦給指針變量 const int* ptr4 = &b; //正確,可以把常量的地址賦給常量指針 *ptr1 = 3; //錯誤,間接引用常量指針不可以修改內存中的數據 *ptr2 = 4; //正確,間接引用指針常量可以修改內存中的數據 ptr1 = &b; //正確,常量指針可以指向其他變量 ptr2 = &b; //錯誤,指針常量不可以指向其他變量 const int * const ptr5 = &a; //常量指針常量,即不可以間接引用修改內存數據,也不可以指向別的變量 *ptr5 = 5; //錯誤,不可以間接引用修改內存數據 ptr5 = &b; //錯誤,不可以修改指向的對象
參考: