引用和指針的那些事
2.3.1 引用
引用并非對象,相反的,它只是為一個已存在對象所起的另外一個名字。
示例:
int ival = 1024;
int &refVal = ival;
Tips:
1.除2種情況外,引用的類型要和與之綁定的對象嚴格匹配
2.引用必須被初始化,且一旦初始化后,它和初始值對象一直綁定在一起,不能更改綁定的對象
3.引用本身不是一個對象,所以不能定義引用的引用
2.3.2 指針
取地址符(操作符&), 解引用符(操作符*)
示例:
int ival = 42;
int *p = &ival;
指針的4種狀態:
a. 指向一個對象
b.指向相鄰對象所占空間的下一個位置
c. 空指針,指針沒有指向任何對象
d. 無效指針,就是上述情況外的其他值
如果指針指向了一個對象,則允許使用解引用符*來訪問該對象(解引用,僅用于有指定對象的有效指針):
如上例操作對象,直接用 *P。
空指針的3種生成方式:
a. int *p1 = nullptr; (C++11新引入,推薦使用)
b. int *p2 = 0;
c. int *p3 = NULL;
Tips:
1.除2種情況外,指針的類型要和它指定的對象嚴格匹配。
2.建議初始化所有指針。
3.賦值操作時,永遠改變的是等號左側的對象。
int *pi = 0;
pi = &ival; //pi的值被改變,現在pi指向了ival
*pi = 0; //ivald的值發生改變
4.將指針作為if語句的判斷條件時,指針值為0,則為false;指針值非0,則為true。
5.void*指針可用于存放任意對象的地址,其內存空間僅僅是內存空間,沒法訪問內存空間所存的對象,
所以void* 指針能做的事比較有限: 拿它和別的指針比較;作為函數的輸入或輸出,或者賦值給另外一個void*指針
補充(理解復合類型的聲明:):
1.
int* p1,p2; //p1是指向int的指針,p2是int型整數
int *p1,*p2; //p1和p2都是指向int的指針
2.指向指針的指針:
通過*的個數可以區分指針的級別,如**表示指向指針的指針。***表示指向指針的指針的指針。,如:
int ival = 1024;
int *pi = &ival; //pi指向一個int型的數(ival)
int **pi = π //ppi指向一個int型指針(pi)
3.面對比較復雜的指針或者引用的聲明語句時,從右向左閱讀有助于弄清它的真實含義。如:
int i =42;
int *p; //p是一個int型的指針
int *&r = p; //r是一個對指針p的引用
r = &i;
*r=0;
第三行,要理解r的類型到底是什么,從右到左閱讀r的定義。離變量名r最近的符號(此例是&r符號的&)對變量的類型最直接的影響,
因此r是一個引用,聲明符的其他部分用來確定r引用的類型是什么(此例中的符號*,說明r引用是一個指針)
2.4 const限定符
1. const對象一旦創建后其值就不能再改變,所以const對象必須初始化。
2. 默認情況下,const對象僅在文件內有效。若想在多個文件中聲明并使用它,需要添加關鍵字extern:
//file_1.cc
extern const int bufSize = fcn();
//file_1.hh頭文件,與cc中定義的bufSize是同一個
extern const int bufSize;
3.1-Const的引用(常量引用):
const int ci =1024;
const int &r1 = ci; //正確,引用及其對應的對象都是常量
Tips:
a. 允許為一個常量引用綁定一個非常量的對象、字面值,甚至是個一般表達式:
int i = 42;
int &r1 = i;
const int &r2 = i; //正確,允許將const int&綁定到一個普通的int 類型
const int &r3 = 42; //正確
r1 = 0; //正確
r2 = 0; //錯誤,r2是一個常量引用
補充: 常量引用對于引用的對象本身是不是常量未作限定,僅對引用可參與的操作做出了限定
b. 一個常量引用被綁定到另外一種類型上:
double dval = 3.14;
const int &r1 = dval; //r1會綁定到由dval臨時生成的int型臨時量(對象)
3.2-指針和const:
與引用一樣,想要存放常量對象的地址,只能使用指向常量的指針
const double pi = 3.14;
const double *cptr = π //cptr可以指向一個雙精度常量
const指針:
常量指針必須初始化。而且一旦初始化則它的值就不能再改變了。
把*放在const關鍵字之前用以說明是一個常量,也意味著不變的是指針本身的值而非指向的那個值。(從右向左讀)
int errNumb = 0;
int *const currErr = &errNumb; //currErr將一直指向errNumb
const double pi = 3.14;
const double *const pip = π //pip是一個指向常量對象的常量指針
3.3-頂層const:
指針:
頂層const:表示指針本身是一個常量
底層const:表示指針所指的對象是一個常量
int i =0;
int *const p1 = &i; //頂層const
const int ci = 42; //頂層const,不能改變ci的值
const int *p2 = &ci; //底層const
const int *const p3 = p2; //右邊的是頂層const,左邊的是底層const
const int &r = ci; //用于聲明的const都是底層const
執行對象的拷貝操作時,頂層const不受什么影響。但是,拷入和拷出的對象必須具有相同的底層const資格。
或者兩個對象的數據類型必須能相互轉換,一般來說,非常量可以轉換為常量,反之則不行。
int *p = p3; //錯誤:p3包含底層const的定義,而p沒有
p2 = p3; //正確:p2和p3都是底層const
p2 = &i; //正確:int*能轉換成const int*(指的是i)
int &r = ci; //錯誤:普通的int& 不能綁定到int常量上
const int &r2 = i; //正確:const int& 可以綁定到一個普通int上
3.4 constexpr和常量表達式
后續補充
二、處理類型

浙公網安備 33010602011771號