1. 程式人生 > >重溫C++——變數和基本型別

重溫C++——變數和基本型別

文章目錄

基本內建型別

型別 含義 最小尺寸
bool 布林 未定義
char 字元 8位
wchar_t 寬字元 16位
char16_t Unicode字元 16位
char32_t Unicode字元 16位
short 短整型 16位
int 整型 16位
long 長整型 32位
long long 長整型 64位
float 單精度浮點數 6位有效數字
double 雙精度浮點數 10位有效數字
long double 擴充套件精度浮點數 10位有效數字

複合型別

引用

  引用(reference)為物件起了另外一個名字,引用型別引用(refers to)另外一種型別,通過將宣告符寫成&d的形式來定義引用型別,其中d是宣告的變數:

int ival = 1024;
int&
refVal = ival; //refVal是ival的另一個名字 int& refVal2; //錯誤,引用型別必須初始化

一般在初始化變數時,初始值會被拷貝到新建的物件中。然而定義引用時,程式把引用和它的初始值繫結(bind)在一起,而不是將初始值拷貝給引用。一旦初始化完成,引用將和它的初始值物件一直繫結在一起。因為無法令引用重新繫結到另外一個物件,因為引用必須初始化。
  引用只是為一個已經存在的物件另外取了一個名字。

指標

  指標(pointer)是指向(point to)另外一種型別的複合型別。與引用類似,指標也實現了對其他物件的間接訪問。然而指標與引用相比有有很多不同點。其一,指標本身就是一個物件,允許對指標賦值和拷貝,而且在指標的生命週期內它可以先後指向幾個不同的物件。其二,指標無須在定義時賦初值。和其它內建型別一樣,在塊作用域內定義的指標如果沒有被初始化,也將擁有一個不確定的值。
  定義指標型別的方法將宣告符寫成*d的形式,其中d是變數名:

int* p = NULL;	//也可以使用0

複合型別的宣告

  變數定義包括一個基本的資料型別(base type)和一組宣告符。在同一行的定義域居中,雖然基本資料型別只有一個,但是宣告符的形式卻可以不同。也就是說,一條定義語句可能定義出不同型別的變數:

//i是一個int型別,p是一個int指標,r是一個int型的引用
int i = 1024, *p = &i, &r = i;

  經常有一種觀點誤以為,型別修飾符(*和&)作用於本行定義的全部變數。造成這種錯誤看法的原因有很多,其中之一是我們可以把空格寫在型別修飾符和變數名中間:

int* p = NULL;

  感覺int*可以修飾這條語句中的所有變數,其實恰恰相反,基本資料型別是int,而不是int*。*僅僅修飾了p而已,對該宣告語句中的其它變數,它並不產生任何作用:

int* p1, p2;	//p1是int型別的指標,p2是int

  涉及指標或者引用的宣告,一般那有兩種寫法。第一種把修飾符和變數識別符號寫在一起,這種形式強調變數具有複合型別:

int *p1, *p2;	//p1和p2都是指向int的指標

  另一種形式把修飾符和型別名寫在一起,並且每條語句只定義一個變數,這種形式著重強調本次宣告定義了一種複合型別:

int* p1;
int* p2;

  我喜歡第二種寫法!!!

指向指標的指標

  一般來說,宣告符中修飾符的個數並沒有限制。當有多個修飾符連寫在一起時,按照邏輯關係解釋即可。以指標為例,指標是記憶體中的物件,像其它物件一樣有自己的地址,因此允許把指標的地址放到一個一個指標中,通過*的個數可以區分指標的級別:

int ival = 1024;
int* pi = &ival;	//pi指向int
int** ppi = π	//ppi指向int型別的指標

引用指標的引用

  引用本身不是一個物件,因此不能定義指向引用的指標。但指標是物件,所以可以有指標的引用:

int i = 42;
int* p = NULL;	//p是指標
int*& r = p;	//r是指標p的引用
r = &i;			//r即p, 相當於p = &i

const修飾符

const和引用

  可以把引用繫結到const物件上,就像繫結到其它物件一樣,稱為對常量的引用(reference to const)。與普通引用不同的是,對常量的引用不能用來修改它所繫結的物件:

const int ci = 1024;
const int& r1 = ci;
r1 = 42;			//錯誤,r1所引用的物件是常量
int& r2 = ci;		//錯誤,非常量引用不能繫結到常量物件上

  經常把“對const的引用”簡稱為“常量引用”,這不是說引用是常量(因為不能更改引用所繫結的物件,在這個層面上所有的引用都是常量),而是說不能通過引用去改變所繫結的物件。為了對ci進行引用,r1必須有const修飾符,否則就像和r2一樣了。const type&這種形式主要使用在函式傳參中。
  下面的程式碼也是合法的:

int i = 42;
int& r1 = i;
const int& r2 = i;
r1 = 0;
r2 = 0;				//錯誤

  這裡r2同樣有const修飾符,所以不能通過r2改變i

const和指標

指向常量的指標

  和引用一樣,也可以讓指標指向常量或非常量。類似於常量引用,不能通過指向常量的指標(pointer to const)來改變指標所指向的物件。要想存放常量物件的地址,只能使用指向常量的指標:

const double pi = 3.14;
double* ptr = π			//錯誤,pi是個常量,普通(非常量)指標不能指向常量
const double* cptr = π
*cpter = 42;
double dval = 3.14;
*cptr = &dval;

  類似引用,因為piconst修飾,所以cptr必須有const修飾,否則就和ptr一樣,可以通過指標來修改pi的值了。指向常量的指標也可以指向非常量:

double dval = 3.14;
const double* cptr = &dval;

常量指標

  因為指標是物件,所以可以把指標定義為const的,即常量指標(const pointer),表示指標本身是常量。這種型別的指標必須初始化,而且一旦初始化完成,它的值(即存放在指標中的地址)就不能再改變了。把*放在const之前說明指標是一個常量,這樣的寫法表示指標本身的值不變而不是指標所指向的值不變:

int errNumb = 0;
int* const curErr = &errNumb;	//寫成int*的形式更容易理解,表示curErr是指標型別的常量
const double pi = 3.14;
const double* const pip = π

  int*的形式表示curErr是指標型別的,const表示它是常量,既然是某種型別的常量,那就不能修改,所以不能修改curErr的值,它將一直指向errNumb
  同樣的,pipconst double*型別的,第二個const表示pip是常量,所以pip是指向雙精度浮點型別常量的常量指標。第二個const表示pip不能被修改,第一個const表示pip指向的值不能被修改。

頂層const

  頂層const(top-level const)表示物件本身是常量,底層const(low-level const)表示所指向和引用的物件是常量,指標型別既可以是頂層const,也可以是底層const:

int i = 0;
int* const p1 = &i;			//p1是頂層const,不能改變p1的值
const int ci = 42;			//ci是頂層const,不能改變ci的值
const int* p2 = &ci;		//p2是底層const,可以改變p2的值,但是不能通過p2修改所指向的物件
const int* const p3 = p2;	//靠右的是頂層const,靠左的是底層const
const int& r = ci;			//引用的const都是底層const
i = ci;						//頂層const不影響拷貝
p2 = p3;					//同上
int* p = p3;				//錯誤,p3具有底層const,而p沒有
p2 = &i;					//int*可以轉換為const int*
int& r = ci;				//錯誤,int&不能引用const int
const int& r2 = i;			//const int&可以繫結到const 上

例項分析

  以const int* const& r為例,r為對指向常量的指標的常量引用。
  這種複雜的複合型別一般採用從右往左的方式進行解讀:
    &r表明r是一個引用;
    const& r表明不能通過r修改所引用的物件;
    * const& r表明r是所引用的物件是一個指標;
    int* const& r表明指標指向int型別;
    const int* const& r表明r所引用的物件指向的是常量整型;
  第二個const表示r是對常量的引用,即不能通過r改變所引用的物件,第一個const表示指標所指向的物件是常量,即不能通過r來改變所指向的物件。簡單來說r是一個指標,第二個const是頂層的,表示不能通過r來改變指標的值,即r++是錯誤的;第一個const是底層的,表示不能通過r來改變指標所指向的值,*r = 0是錯誤的。