C++引用和const引用、常量指針、指針常量


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; //錯誤,不可以修改指向的對象

 

參考:

引用  常量指針


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM