基本内容
由類型的實際值引用(類似于指針)表示的數據類型。如果為某個變量分配一個引用類型,則該變量将引用(或“指向”)原始值。不創建任何副本。引用類型包括類、接口、委托和裝箱值類型。
一些計算機高級語言有引用類型這種變量類型。
一、C語言中沒有引用類型。
二、C++中的引用類型:
“引用”(reference)是c++的一種新的變量類型,是對C的一個重要補充。它的作用是為變量起一個别名。假如有一個變量a,想給它起一個别名,可以這樣寫:
int a;int&b=a;
這就表明了b是a的“引用”,即a的别名。經過這樣的聲明,使用a或b的作用相同,都代表同一變量。在上述引用中,&是“引用聲明符”,并不代表地址。
不要理解為“吧a的值賦給b的地址”。聲明引用并不開辟内存單元,b和a都代表同一變量單元。
注意:在聲明引用變量類型時,必須同時使之初始化,及聲明它代表哪一變量。在聲明一個變量的引用之後,在本函數執行期間,該引用一直與其代表的變量相聯系,不能再作為其他變量的别名。下面的用法不對:
int a1,a2;
int&b=a1;
b=a2;//企圖使b變成a2的别名(引用)是不行的。
例1:
#include
#include
void main()
{
int a=10;
int&b=a;//聲明b是a的引用,這樣a的值變以後,b的值也變;b的值變以後,a的值也跟着變。
a=a*a;
cout<
b=b/5;
cout<
}
有了變量名,為什麼還需要一個别名呢?C++之所以增加“引用”,主要是把它作為函數參數,以擴充函數傳遞數據的功能。
我們知道,在C語言中,函數參數傳遞是單向的,所以例4不能實現兩個變量值的交換。C語言中,數組作為函數參數傳遞的是數組的首地址。
C語言中,還可以利用指針變量做形參來實現兩個變量值的換,但這種方式需要定義指針變量,需要額外開辟存儲空間,來存放地址,見例3。而引用變量不是獨立的變量,不單獨占内存單元這種方法,實參向形參傳送的是實參的地址(但與指針不同的是掉用函數時不需要&),而不是實參的值,見例2。
看到&a這種形式時,怎樣區分是指針還是引用呢?一般而言,見到前面有類型說明符(如int&a),是引用,而前面沒有類型說明符時(如&a)認為是指針。
例2:
//函數參數傳遞之引用調用
#include
void swap(int&a,int&b)
{
int temp;
temp=a;
a=b;
b=temp;
}
void main()
{
int i=3,j=5;
swap(i,j);
cout<<"i="<
cout<<"j="<
}
例3:
//函數參數傳遞之傳地址調用(通過指針)
#include
void swap(int*a,int*b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void main()
{
int i=3,j=5;
swap(&i,&j);
cout<<"i="<
cout<<"j="<
}
例4:
//錯誤程序例:這個程序不能實現i和j值的交換。
#include
void swap(int a,int b)
{
int temp;
temp=a;
a=b;
b=temp;
}
void main()
{
int i=3,j=5;
swap(i,j);
cout<<"i="<
cout<<"j="<
}
備注:注意C++中引用類型與類的區别。
參考文獻:東北大學出版社-李一波編着《新概念C語言》218頁
清華大學出版社陳天華編着《面向對象程序設計與VisualC++教程》73頁
三、C#中也有引用類型。
區别
看實例吧:
引用是C++中的概念,初學者容易把引用和指針混淆一起。
下面的程序中,n是m的一個引用(reference),m是被引用物(referent)。
int m;
int&n=m;
n相當于m的别名(綽号),對n的任何操作就是對m的操作。
所以n既不是m的拷貝,也不是指向m的指針,其實n就是m它自己。
引用的規則
(1)引用被創建的同時必須被初始化(指針則可以在任何時候被初始化)。
(2)不能有NULL引用,引用必須與合法的存儲單元關聯(指針則可以是NULL)。
(3)一旦引用被初始化,就不能改變引用的關系(指針則可以随時改變所指的對象)。
以下示例程序中,k被初始化為i的引用。
語句k=j并不能将k修改成為j的引用,隻是把k的值改變成為6。
由于k是i的引用,所以i的值也變成了6。
int i=5;
int j=6;
int&k=i;
k=j;//k和i的值都變成了6;
主要功能
在C++中可以定義“引用”。定義方式如下:類型名&引用名=同類型的某變量名;
引用的主要功能:傳遞函數的參數和返回值。
C++語言中,函數的參數和返回值的傳遞方式有三種:值傳遞、指針傳遞和引用傳遞。
以下是"值傳遞"的示例程序。
由于Func1函數體内的x是外部變量n的一份拷貝,改變x的值不會影響n,所以n的值仍然是0。
void Func1(int x)
{
x=x+10;
}
...
int n=0;
Func1(n);
cout<<"n="<
void Func3(int&x){x=x+10;}...int n=0;Func3(n);cout<<"n="<
(1)在實際的程序中,引用主要被用做函數的形式參數--通常将類對象傳遞給一個函數.引用必須初始化.但是用對象的地址初始化引用是錯誤的,我們可以定義一個指針引用。
1int ival=1092;
2int&re=ival;//ok
3int&re2=&ival;//錯誤
4int*pi=&ival;
5int*&pi2=pi;//ok
(2)一旦引用已經定義,它就不能再指向其他的對象.這就是為什麼它要被初始化的原因。
(3)const引用可以用不同類型的對象初始化(隻要能從一種類型轉換到另一種類型即可),也可以是不可尋址的值,如文字常量。例如:
double dval=3.14159;
//下3行僅對const引用才是合法的
const int&ir=1024;
const int&ir2=dval;
const double&dr=dval+1.0;
上面,同樣的初始化對于非const引用是不合法的,将導緻編譯錯誤。原因有些微妙,需要适當做些解釋。
引用在内部存放的是一個對象的地址,它是該對象的别名。對于不可尋址的值,如文字常量,以及不同類型的對象,編譯器為了實現引用,必須生成一個臨時對象,引用實際上指向該對象,但用戶不能訪問它。
例如:
double dval=23;
const int&ri=dval;
編譯器将其轉換為:
int tmp=dval;//double->int
const int&ri=tmp;
同理:上面代碼
double dval=3.14159;
//下3行僅對const引用才是合法的
const int&ir=1024;
const int&ir2=dval;
const double&dr=dval+1.0;
内部轉化為:
double dval=3.14159;
//不可尋址,文字常量
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;//正确
(5)********對于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的語義是什麼。const引用表示,試圖通過此引用去(間接)改變其引用的對象的值時,編譯器會報錯!這并意味着,此引用所引用的對象也因此變成const類型了。我們仍然可以改變其指向對象的值,隻是不通過引用。下面是一個簡單的例子:
1#include
2using namespace std;
3
4int main()
5{
6int val=1024;
7const int&ir=val;
8
9val++;
10//ir++;
11
12cout<<"val="<
13cout<<"ir="<
14return0;
15}
其中第10行,如果我們通過ir來改變val的值,編譯時會出錯。但是我們仍然可以通過val直接改變其值(第9行)
總結:const引用隻是表明,保證不會通過此引用間接的改變被引用的對象!
另外,const既可以放到類型前又可以放到類型後面,放類型後比較容易理解:
string const*t1;
const string*t1;
typedef string*pstring;string s;
const pstring cstr1=&s;就出錯了
但是放在類型後面不會出錯:
pstring const cstr2=&s;



















