復合型別,顧名思義就是指基於其他型別定義的型別,主要有***指標***與***引用***。本文將先分別介紹這兩種型別,接著將介紹二者之間的異同之處。
一般來講,一條宣告通用的格式為:基本資料型別 宣告符
。在簡單宣告語句中,宣告符就是變數名,換句話說,此時的變數型別就是宣告符前面的基本資料型別。而復合型別就是一種基於基本資料型別的更為複雜的資料型別。
*指標是一中「指向」另外一種型別的復合型別。簡而言之,指標是一種實現對物件間接訪問的型別。指標本身也是物件,該物件存放了指標所指物件的位址,以此來實現對物件的間接訪問。
定義指標型別的方法就是將宣告符寫成*p
格式,其中p是變數名,在一條宣告語句中可以宣告多個指標型別的變數,每個變數名前必須有。具體格式如下:
int *p, *q; //宣告了兩個指標型別的變數p和q,p,q都指向int型別的物件
double *p, i; //宣告了乙個指令型別的變數p,該變數p指向乙個double型別的物件和乙個double型別變數i
既然指標物件儲存的是指標所指物件的位址,那麼如何獲取物件的位址呢?通常在變數名前加**&**符號來獲取物件的位址。
int i = 41; //定義並初始化乙個int型別的變數i
int *p = &i; //定義乙個指向int型別物件的指標p,p存放的是i的位址,也就是說p是指向i的指標。
注意:這裡的符號&
是取位址符**,和之後將要在引用章節中提到的**&有著不同含義在那裡是引用宣告符**。
一般來說,指標的型別必須和它所指向的物件嚴格匹配。因為在一條宣告語句中指標的型別實際上是用來指定它所指向物件的型別,所以二者必須嚴格一致。
double d; //宣告乙個double 型別的物件d
int *p = &d; //錯誤:不可以用int型別的指標指向乙個double型別的物件
double *q = &d; //正確:可以用double型別的指標指向乙個double型別的物件
###指標的值
通常,指標的值無外乎以下4中:
賦值與訪問
賦值和訪問可以分為對指標本身的賦值和訪問以及對指標所指物件的賦值和訪問。
char *p1 = "abc", *p2= p1;//指標p1和p2都指向字串"abc"的首位址
int a = 2, b = 3;
int *p3 = &a;//對指標本身的賦值,將int型別變數a的位址賦值給p3
p2 = p1 + 1;//對指標本身的運輸和賦值,此時p2將指向字串"abc"的'b'的位址
cout << *p3 << endl;//訪問p3所指向的物件
**引用是為物件取的乙個別名,引用型別引用另外一種型別通過將宣告符寫成&f
形式來定義引用型別。
int ival = 2;
int &reval = ival;//引用必須初始化
學習引用必須時刻注意它的定義:引用是為物件起的另外乙個***別名***,簡而言之,提到引用第一反應就是***別名***。這樣,很多問題就迎刃而解,比如:引用必須初始化,引用是別名,不初始化怎麼知道它是哪個物件的別名,再比如,引用一經初始化就不能再指向其他物件了,否則,作為別名卻指向多個物件,這樣就相當於乙個乙個引用是多個物件的別名。
既然引用就是其所引用物件的別名,所以,對引用的操作就是對所引用物件的操作。
首先簡單的介紹一下***const***這個宣告限定符,被const修飾的變數和普通變數大體沒有出別,本const修飾物件主要限制在於對該變數的操作指限於不改變其內容的操作。還有乙個必須了解的是,const只影響被它修飾的物件,時刻記住這一點是十分有必須要的。
指向常量的物件的指標,顧名思義,就是指標所指向的物件是常量,但是也不完全對,因為這樣乍看好像並沒有什麼問題,但是如果細想,被指物件是常量,當然是不想被修改,現在有指標指向它,是不是可以通過指標修改它呢?舉例說明:
const double pi = 3.14;
double r = 1;
double *p = & pi; /*錯誤:變數pi是乙個double型別常量,如果本語句正確,那麼程式設計師將可以通過指標p來改變pi的值了*/
const double *p1 = π /*正確:指向常量物件的指標,無論通過指標p1還是變數pi本身都不能改變pi的值*/
const double *p2 = &r;//正確:將乙個指向常量的指標指向乙個普通變數
從上面的**中,我們可以看出,可以將乙個指向常量的指標指向乙個常量或者普通變數,二者的主要出別在意前者不論通過指標還是變數本身都不能改變變數的值,而後者則不同——不可以通過指標來改變變數的值,但是可以通過變數本身來改變。總之,出別這一點的關鍵在要始終記住,const影響的只是它所修飾的那個變數,和其他的沒有關係。
現在,我們應該會想到,指標需要從兩個方向來思考——指標本身和指標所指向的物件。指標本身也是物件當然也可以被const修飾。這就是這一小結中的***常量指標***。正如該名稱所示,常量修飾的是***指標***,就是說常量指標一經初始化後就不能再指向其他物件。那麼問題又來了,是否可以通過常量指標修改其指向物件的值呢?答案是肯定的,正如上文所講,const 只影響被其修飾的物件,和其他物件無關。
double pi = 3.14;
double *const p = π //常量指標
從上面的例項**中我們可以知道,常量指標所指物件也不必是常量。
和指標類似,引用也可以指向乙個常量物件,也可以通過const限制引用不可修改所指物件。與指標不同之處在於兩者都是常量引用,即對const的引用。這裡,我們要記住,引用不是物件,只是被引用物件的別名而已。引用一經繫結便不可以改變其繫結的物件,那麼就不存在類似與常量指標的概念了,換而言之,在引用關係這個層面上是不受const的影響的。const所能夠影響的只有對物件的操作上,因此,在講const和引用時,我們只需關注引用和被引用物件操作上,不必關心引用關係。可能有讀者就會有疑問了,如果乙個物件可以通其本身來改變,但是不能通過引用來改變該如何操作?
int a = 12;
const b = 13;
const int &c = b;//將常量引用繫結到乙個常量上
const int &d = a; //將乙個常量繫結到乙個普通物件上
此次,容易使人迷惑的是,乙個對const 的引用卻可以繫結到乙個普通變數上。其實,也不難理解,因為我們有上面的需求——可以通過變數本身改變變數額度值,但是不可以通過引用來改變。要更好的理解這個問題,我們需要知道它是如何實現的,const int &d = a
其實等價於:
const int temp = a;
const int &d = temp;
簡單來講,就是變壓器對**做了轉換,d實際上繫結到了乙個***臨時變數*** temp上。
區別指標和指標所指向的物件
指標是物件,其中存放的是其所指物件的位址
指標所指物件是,指標物件所存位址對應空間存放的內容
const限定符只影響它所修飾的變數。
引用是變數的乙個別名,記住這一點將解決大部分關於引用的疑惑
變數和它的引用之間是繫結關係,而非賦值關係,即,對引用值的修改將改變變數的值
定義引用時必須對其進行初始化,且初始化必須是乙個變數,否則,將不知道引用到底是誰的別名
初始化一旦完成,變不可更改,也就是說該引用不可再繫結到其他變數上了,否則,乙個別名將是若干個變數的別名,這樣將導致不知道別名到底繫結了哪變數了。
因為引用只是乙個別名而已,所以引用不是物件,沒有實際的位址,進而得出,不能定義指向引用的指標
C 復合型別 引用和指標
include using namespace std 復合型別 基於其他型別定義的型別 常見 引用 指標 引用 1.右值引用 rvalue reference 2.左值引用 lvalue reference 引用必須是乙個物件,引用就是起乙個別名,引用必須初始化。指標 是 指向 point to ...
指標和引用 復合型別的宣告
引用 引用是對物件起乙個別名,即相互繫結的意思,引用不像指標那樣可以指向不同物件,不可解綁,引用不是乙個物件,所以必須進行初始化。如 int a int b a 即b是a的別名,a的值也是b的值,改變a或b的值兩者值都會改變。引用只能繫結在物件上,不能繫結在字面值或某個表示式的結果上。如 int i...
C 復合型別之引用和指標
復合型別是指基於其他型別定義的型別。c 有很多復合型別,介紹其中的引用和指標 對變數的宣告的解釋 一條簡單的宣告語句是由乙個資料型別和緊隨其後的變數名列表組成。其實更通用的描述是 一條宣告語句由乙個基本資料型別和緊隨其後的乙個宣告符列表組成。每個宣告符命名了乙個變數並指定該變數是與基本資料型別有關的...