復合型別(compound type)是指基於其他型別定義的型別。c++語言有幾種復合型別,這裡將介紹兩種復合型別引用和指標。
與我們已經掌握的變數宣告相比,定義復合型別的變數要複雜很多。一條簡單的宣告語句由乙個資料型別和緊隨其後的乙個變數名列表組成。其實更通用的表述是,一條宣告語句由乙個基本資料型別(base type)和緊隨其後的宣告符(declarator)列表組成。每個宣告符命名了乙個變數並指定該變數與基本資料型別有關的某種型別。
目前為止,我們所接觸的宣告語句中,宣告符其實就是變數名,此時變數的型別也就是宣告的基本資料型別。其實還可能有更複雜的宣告符,它基於基本資料型別得到的更複雜的型別,並把它指定給變數。
引用(reference)是c++對c語言的重要擴充。引用就是某種目標變數的「別名」(alias),對引用的操作與對變數直接操作的效果相同。申明乙個引用的時候,切記要對其初始化。引用宣告完畢後,相當於目標變數名有兩個名稱,即該目標原名和引用名,不能再把該引用名作為其他變數的別名,他本省不是一種資料型別,因此引用本省不佔儲存單元,系統也不給引用分配儲存單元。不能建立陣列的引用。
引用型別名 & 引用名 = 被引用的變數;
被引用的變數應該是已宣告或已定義的變數。
引用既然是乙個變數的別名,那麼,兩者的資料型別必須相同,而且在宣告引用時必須同時初始化(除引用是用做函式的引數或者是返回值),說明它是哪一種變數的引用。
例如:
int a;
int &ra = a; // ra 指向 a (是 a 的另外乙個名字)
int &ra2; // 報錯:引用必須初始化
一般在初始化變數時,初始值會被拷貝到新建的物件中。然而定義引用時,程式把引用和他的初始值繫結(bind)在一起,而不是將初始值拷貝給引用。一旦初始化完成,引用將和它的初始值物件一直繫結在一起。因為無法令引用重新繫結到另外乙個物件,因此引用必須初始化。
引用並非物件,相反的,他只是為乙個已經存在的物件所起的另外乙個名字允許在一條語句中定義多個引用,其中每個引用識別符號都必須以符號&開頭:
int i = 1024, i2 = 2048; // i和 i2 都是 int
int &r = i, r2 = i2; // r 是乙個引用,與 i 繫結在一起,r2 是 int
int i3 = 1024, &ri = i3; // i3 是int ,ri 是乙個引用,與 i3 繫結在一起
int &r3 = i3, &r4 = i2; // r3 和 r4 都是引用
/* 錯誤示例 */
int &a = 10; // 錯誤:引用型別的初始值必須是乙個物件
double a = 3.14;
int &ai = a; // 錯誤:此處引用型別的初始值必須是 int 型物件
宣告引用時,如果不同時初始化以指明它與哪個已宣告(或定義)的變數相關聯,則會出現編譯錯誤。
int a = 10, b = 20;
int &ra; // 錯誤,引用 ra 未被初始化
int &ra = b; // 正確
引用宣告的字元「 & 」並不是位址運算子,它只是用來宣告引用,除此之外,其他的應用都屬於位址運算子。
int a = 20;
int &ra = a; // ra 是 a 的引用,& 是引用的宣告符
int *p;
p = &a; // & 是位址運算子
引用一旦被初始化,將它與某個變數關聯起來後,就不會再分開。與此不同,指標在賦予某變數位址後,可以指向其他變數。
int a = 20, b = 30;
int &ra = a; // 指定引用 ra 與 a 關聯,ra = 20
···ra = b; // ra 仍與 a 關聯,此時,ra = 30,a = 30
不允許對 void 型別進行引用。
void a = 10;
void &ra = a; // 錯誤
因為 void 只是語法上的乙個型別,不能建立乙個型別為 void 的變數。因此不能生命對 a 的引用。
不能建立陣列的引用。
int array[s];
int &ra = array; // 錯誤,array 只是 array[s] 的起始變數
與指標不同,引用本身不是變數,指標是變數。
指標可以有引用。
int * p;
int *&rp = p; // rp 是指標 p 的引用
int b = 10;
rp = &b; // 正確,rp 是指標 p 的別名,指向變數 b
指標可以作為陣列的元素,引用不可以做為陣列的元素。
將「引用」作為函式引數的特點:
傳遞引用給函式與傳遞指標的作用效果是一樣的。這時,這時被調函式的形參就成為原來主調函式的實參或者物件的乙個別名來使用,所以在被調函式中對形參的操作就是對其相應的目標物件的操作。
使用引用傳遞函式的引數,在記憶體中並沒有實參的副本,它是實參操作;而使用一般變數傳遞函式的引數,當發生函式呼叫時,需要給形參分配記憶體單元,形參變數是實參變數的副本;如果傳遞的是物件,還將呼叫拷貝建構函式。
例子:用引用作為引數,交換兩個數
#include
using namespace std;
void
swap
(int
& x,
int& y)
void
main()
程式執行結果:
交換前: a = 1,b = 2
交換後: a = 2,b = 1
函式中的形參是主調函式中實參的引用。在函式中改變了形參,就是改變了實參,因此交換功能實現。
例子:用一般變數作為引數,交換兩個數
#include
using namespace std;
void
swap
(int x,
int y)
void
main()
程式執行結果:
交換前: a = 1,b = 2
交換後: a = 1,b = 2
主函式的變數 a 和 b 的值(副本)作為實參進棧。採用傳值方式時,實參不受影響。
以引用作為函式的返回值是為了使函式可以作為左值而被賦值。函式的返回值為引用型別表示表示該函式的返回值是乙個記憶體變數的別名。函式呼叫既可以作為乙個變數來使用,也可以為其賦值。
例子:
/* 求兩個數中最小值 */
#include
using namespace std;
int&
min(
int& i,
int& j)
void
main()
程式執行結果:
a = 3 b = 4
a = 5 b = 4
a = 5 b = 0
注意事項: c 學習筆記(1)復合型別
復合型別是指基於其他型別定義的型別。接下來介紹c 復合型別中的兩種 應用和指標。通過將宣告符寫成 d的形式來定義應用資料型別,其中d是宣告的變數名。int a 0 宣告基本資料型別 int refa a 宣告引用資料型別,refa指向a,是a的另外乙個名字 int refb 錯誤,引用必須被初始化為...
C 復合型別
陣列 陣列是一種資料格式,能夠儲存多個同型別的資料。宣告陣列的通用格式 typename arrayname arraysize arraysize指定了元素的個數,它必須是整型常量 20或者const值 也可以是表示式,但是其中的所有值在編譯時必須是已知的,所以說arraysize不是變數,變數的...
C 復合型別
include include include include include using namespace std 學習進度c primer plus第4章 復合型別 陣列 c風格字串 string變數 getline 和get 結構體 共用體 列舉 指標 new與delete管理動態記憶體 建...