指針和引用是C/C++中兩個(gè)非常重要的概念,這兩天看了下“指針”和“引用”的
wikipedia詞條,對(duì)他們有了一些新的認(rèn)識(shí),這里記錄下個(gè)人的理解和想法,也可以引申到其他語(yǔ)言。
指針
我們都知道*p表示指針
但其實(shí)這個(gè)*符號(hào)是有兩種意義的,兩種不同的意義。
- 在定義變量的時(shí)候,*表示這是一個(gè)指針,它只是一個(gè)標(biāo)識(shí)符,表示這是一個(gè)指針變量
- 在其他時(shí)候,非定義語(yǔ)句中,*是解引用運(yùn)算符 ——用來(lái)解出變量指向的那個(gè)地址的值
eg.
int a = 10;
int *p = &a; // 這里*只是一個(gè)標(biāo)識(shí)符,標(biāo)識(shí)p是一個(gè)“指針變量”,p的值為a的地址(&a為取地址,注意c里面沒(méi)有“引用”的概念)
int function test(*p)
{
}
test(&a);
//這里的*p是解引用運(yùn)算符,表示p這個(gè)“指針變量”指向的值。
綜上,注意*p中的*是解引用運(yùn)算符,表示p這個(gè)指針變量所指向的值,比如int *p=&a,那這個(gè)*p就是一個(gè)普通的整型變量,跟普通的整型變量沒(méi)什么區(qū)別,一樣使用方式。也就是說(shuō)看到*p的時(shí)候就當(dāng)做一個(gè)普通變量一樣使用就行了。
“指針變量”這個(gè)詞指的是 p,是一個(gè)內(nèi)存地址。指針是一個(gè)變量,變量值為一個(gè)內(nèi)存地址,*p解引用取出這個(gè)內(nèi)存地址上保存的值。
舉個(gè)例子,做個(gè)比較:
int a; //定義一個(gè)變量a,用于保存一個(gè)int類(lèi)型。
int * b; //定義一個(gè)指針變量b,用于保存一個(gè)地址,這個(gè)地址所保存的數(shù)據(jù)應(yīng)該是int類(lèi)型。
p和*p的關(guān)系是什么?
我們有一個(gè)指針變量
p,p表示地址,*p表示值。
例如,給指針賦值,接著上面的例子:
b=&a; //把變量a的地址賦值給b。"&"操作是取變量的地址。
這里地址就是賦給b而不是*b,因?yàn)閎表示地址而*b表示地址存儲(chǔ)的變量。
繼續(xù)舉例:
int * c; //我們又定義一個(gè)指針c
c=b; //將b的值賦值給c,上面已經(jīng)知道b是指針,它的值是a的地址,那么現(xiàn)在c 的值和b一樣,也是個(gè)a的地址。
-
指針有什么用?
比方說(shuō),我們有個(gè)函數(shù),如下:
int add(int x){
return (x+1); //把輸入的值加1并返回結(jié)果。
}
好了,應(yīng)用的時(shí)候是這樣的:
{
int a=1;
a=add(a); //add函數(shù)返回的是a+1
//現(xiàn)在 a等于2
}
很簡(jiǎn)單吧,就是把a(bǔ)都累加一次。
用指針怎么寫(xiě):
void add(int *y){ //給入的是一個(gè)int指針,是一個(gè)地址。
*y = *y + 1; //* 是指引用 這個(gè)地址所保存的變量
//這條語(yǔ)句的意思就是,把這個(gè)地址里的值加1,然后放回這個(gè)地址。
}
把這個(gè)函數(shù)用起來(lái):
{
int a=1;
add(&a); //把a(bǔ)的地址傳到函數(shù)里
//add函數(shù),就是把a(bǔ)的值加1,再放回到變量a里。
//現(xiàn)在a等于2
}
- 為什么要使用指針?
函數(shù)的參數(shù)傳遞都是值傳遞,也就是會(huì)把變量復(fù)制一份傳遞,這樣如果數(shù)據(jù)比較大,效率很低,而使用指針傳遞的話,只需要復(fù)制一個(gè)內(nèi)存地址傳遞(指針也是一個(gè)值),效率很高很快,可以節(jié)省時(shí)間和空間。
- 為什么空指針很危險(xiǎn)?
我們知道,一個(gè)變量要賦值后才能用,指針也是一樣。指針不賦值(不給定地址)就拿來(lái)用,是不是也要出錯(cuò)。這個(gè)就是空指針。一般把指針賦值為Null,就是表明這個(gè)指針是空的,不能用。所以程序中一定要經(jīng)常判別指針不是Null才能用。
引用
所謂引用的概念,在 C里面是沒(méi)有的,是C++提出的概念,因?yàn)橹羔槻话踩?,容易錯(cuò)誤使用,產(chǎn)生內(nèi)存問(wèn)題。
java不支持使用指針,c++支持有限的使用指針(為了保持對(duì)c的兼容)
他們提供了引用用來(lái)代替指針的功能。
注意:在C中沒(méi)有引用的概念,&在C里面只表示取地址。
所謂引用,可以理解為變量的“別名”
指針是最簡(jiǎn)單的引用。
引用的用法類(lèi)似指針:
eg.
int a = 10;
int &b = a; //這里b就是變量a的一個(gè)引用,相當(dāng)于a的別名。
//指針和引用都是對(duì)變量的,無(wú)法對(duì)常量引用,而雖然可以對(duì)常量建立指針不過(guò)沒(méi)什么意義。
引用與指針的區(qū)別------wikipedia
對(duì)于同時(shí)支持引用與指針的C/C++,兩類(lèi)數(shù)據(jù)型的區(qū)別有:
- 指針可以重新賦值,而引用在初始化綁定后就不能再綁定到其他對(duì)象。
- 指針對(duì)象有它自己的內(nèi)存地址與內(nèi)存長(zhǎng)度,而引用與它指向的對(duì)象具有相同的內(nèi)存地址、內(nèi)存長(zhǎng)度。因此,可以把引用看作是被指向?qū)ο蟮牧硪粋€(gè)名字。
- 指針可以指向另一指針,因此允許多層的指針間址(indirection);而引用只允許到對(duì)象的一層間址,不允許“引用的引用”。
- 指針可以直接賦值為NULL,引用不能。當(dāng)然,可以費(fèi)勁辦法把引用綁定到內(nèi)存的NULL上,但這并不實(shí)用。
- 指針可以在數(shù)組上遍歷(iterate),引用不能。
- 指針需要用運(yùn)算符
*來(lái)解引用(dereference)以訪問(wèn)它所指向的內(nèi)存的內(nèi)容;引用需要顯式的解引用。指向類(lèi)/結(jié)構(gòu)的指針訪問(wèn)成員變量/成員函數(shù)需要用運(yùn)算符->而引用使用運(yùn)算符.來(lái)訪問(wèn)成員。 - 指針是一個(gè)變量,保存了內(nèi)存地址;而C/C++標(biāo)準(zhǔn)都沒(méi)有明說(shuō)引用是如何實(shí)現(xiàn)的。實(shí)際上,幾乎所有C/C++編譯器把引用作為一個(gè)隱式的指針來(lái)實(shí)現(xiàn)。
- 指針可以成為數(shù)組的成員類(lèi)型,即指針數(shù)組;但引用不可以作為數(shù)組的成員類(lèi)型,即不存在“引用數(shù)組”。
- const引用可以綁定到臨時(shí)對(duì)象;而指針不能(例如,int *y = 12;編譯出錯(cuò))。按照C++11語(yǔ)法,const左值引用可以綁定到一切對(duì)象,包括const左值對(duì)象,非const左值對(duì)象,const臨時(shí)對(duì)象,非const臨時(shí)對(duì)象;右值引用當(dāng)然可以綁定到臨時(shí)對(duì)象。