欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c++基礎(chǔ)學(xué)習(xí)之如何區(qū)分引用和指針

 更新時(shí)間:2021年08月20日 10:43:02   作者:努力學(xué)習(xí)的少年  
C語言中只有指針,C++加入了引用,能夠起到跟指針類似的作用,下面這篇文章主要給大家介紹了關(guān)于c++基礎(chǔ)學(xué)習(xí)之區(qū)分引用和指針的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

對(duì)于我剛學(xué)c++的時(shí)候,最令我頭疼的是引用和指針,老是區(qū)分不了它們,那么今天筆者將我的學(xué)習(xí)到的筆記總結(jié)出來,讓大家少走一些坑。

術(shù)語:什么是對(duì)象?(對(duì)象在下面將會(huì)一直提到)

    c++程序員們?cè)诤芏鄨龊隙紩?huì)使用對(duì)象這個(gè)名詞,通常情況下,對(duì)象是指一塊能存儲(chǔ)數(shù)據(jù)并具有某種類型的內(nèi)存空間。有些人僅在與類有關(guān)的場景下才使用“對(duì)象”這個(gè)詞。在這里,即認(rèn)為對(duì)象是具有某種數(shù)據(jù)類型的內(nèi)存的空間

1.引用

1.1引用的概念

引用為對(duì)象起另外一個(gè)名字,通過聲明符寫成&d的形式來定義引用類型,其中d是聲明的變量名。

    int i = 10;
	int& refi = i;//refi是i的另外一個(gè)名字
	int& refi2;//報(bào)錯(cuò):引用必須初始化

一個(gè)對(duì)象可以有多個(gè)引用,相當(dāng)于給對(duì)象起多個(gè)名字。

    //refi,refi1,refi2與i綁定在一起
    int& refi1 = i;
	int& refi2 = refi1;

定義引用時(shí),程序把引用和它的初始值綁定在一起,而不是將初始值拷貝給引用。一旦引用無法重新綁定到另外一個(gè)對(duì)象,因此引用必須初始化。

定義引用后,對(duì)它進(jìn)行所有的操作都是與之綁定的對(duì)象上進(jìn)行的。

  refi = 100;//將100的值賦值給refi,即把值給i
  int j=refi;//與int j=i;是一樣的

1.2引用的定義

允許在一條語句中定義多個(gè)引用,其中每個(gè)引用標(biāo)識(shí)符都必須以符號(hào)&開頭。

	int i = 10, int i1 = 10;//i和i1都是int型
	int& r = i, int i1 = i;//r是引用,與i進(jìn)行綁定,i1是int
	int i3 = i1, & r2 = i1;//i3是int,r2是引用,與i1綁定一起
	int& r3 = i, & r4 = i;//r3和r4都是引用

除特殊情況下(下面會(huì)講),引用需要與要綁定的對(duì)象嚴(yán)格匹配,而且引用只能綁定在對(duì)象上,不能與字面某個(gè)值或某個(gè)表達(dá)式的計(jì)算結(jié)果綁定在一起。

    int& refi = 10;//錯(cuò)誤:引用類型的初始值必須是一個(gè)對(duì)象
	int i = 10;
	double& d = i;//錯(cuò)誤:引用的類型必須是int型

1.3引用與const

把引用綁定到const對(duì)象上,我們稱之為對(duì)常量的引用,與普通引用不同的是,對(duì)常量引用不能被做修改它所綁定的值。

    const int i = 10;
	const int& r1 = i;//正確:引用及其對(duì)應(yīng)的對(duì)象都是常量
	const int& r2 = 200;//正確:引用及其對(duì)應(yīng)的對(duì)象都是常量
	r1 = 40;//錯(cuò)誤:r1是常量的引用,不能修改
	int& r2 = r1;//錯(cuò)誤:r1是常量引用,只能讀,r2是非常量引用,能讀能修改

術(shù)語:c++程序員們經(jīng)常把詞組“對(duì)const的引用”簡稱“常量引用”。

在我們之前提到,引用的類型必須與其所引用的對(duì)象的類型一致,但是有兩個(gè)例外,第一種是情況是初始化常量引用時(shí)允許用任意表達(dá)式作為初始值,只要該表達(dá)式的結(jié)果能轉(zhuǎn)換為引用類型即可,第二種是,常量引用可以綁定非const對(duì)象可以綁定。

	int i = 42;
	const int& r1 = i;//正確:允許將const int&綁定到一個(gè)普通int對(duì)象上
	const int& r2 = i * 2;//正確:r2是一個(gè)常量引用
	int& r3 = i * 2;//錯(cuò)誤:r3是一個(gè)普通的非常量引用

而且對(duì)于常量引用還有更神奇的地方是:

	double d1 = 1.111;
	const int& r3 = d1;

上面的代碼是正確的,r3是一個(gè)常量int類型的&引用,按理說應(yīng)該只能綁定int類型的常量引用,單d1是一個(gè)double類型的對(duì)象 ,但編譯器為了確保讓r3綁定一個(gè)int類型對(duì)象,編譯器自動(dòng)把上述代碼轉(zhuǎn)換為:

	const int tmp = d1;//由double生成一個(gè)int類型的臨時(shí)量
	const int& r3 = tmp;//讓r3綁定這個(gè)臨時(shí)量tmp

此處r3是綁定了臨時(shí)量,而非d1對(duì)象,所謂的臨時(shí)量對(duì)象就是當(dāng)編譯器需要一個(gè)空間來暫存表達(dá)式的求值結(jié)果時(shí)臨時(shí)創(chuàng)建的一個(gè)未命名的對(duì)象。

對(duì)const引用可以引用非const對(duì)象:

	int i = 10;
	int& r1 = i;
	const int& r2 = i;//正確:const引用可以引用非const對(duì)象,但是不能通過r2修改i
	r1 = 20;//正確:r1為非const引用,可以修改
	r2 = 30;//錯(cuò)誤:r2為cosnt引用,不能對(duì)i進(jìn)行修改

1.4引用的使用場景

1.做參數(shù)

 void Swap(int& left, int& right)
 {
    int temp = left;
    left = right;
     right = temp;
 }
  
int main()
{
   int a=0,b=10;
   swap(a,b);
}

引用可以用來做參數(shù),把對(duì)象傳給函數(shù)時(shí),則函數(shù)中的參數(shù)則綁定到對(duì)應(yīng)的對(duì)象中,不會(huì)產(chǎn)生臨時(shí)變量例如:left則則是a的引用,right則是b的引用。

 2.做返回值

int& Count()
{
 static int n = 0;//n存在靜態(tài)區(qū)中
 n++;
 return n; //返回對(duì)象是n的引用
}
 
int& Add(int a, int b)
 {
 int c = a + b;
 
 return c;
}
 
int main()
{
 //這是錯(cuò)誤的:因?yàn)閏出了函數(shù)作用域后則會(huì)被銷毀,則c這塊空間就不存在
 //ret引用就無效。
  int& ret=ADD(1,2);
}

總結(jié):

如果函數(shù)返回時(shí),出了函數(shù)作用域,如果返回對(duì)象還未還給系統(tǒng),則可以使用引用返回,如果已 經(jīng)還給系統(tǒng)了,則必須使用傳值返回。

2.指針

2.1概念

指針是“指向”另外一種類型的復(fù)合類型。指針是用來存儲(chǔ)變量的地址,本身就是一個(gè)對(duì)象,允許對(duì)指針進(jìn)行賦值和拷貝,而且指針的生命周期內(nèi)它可以先后指向不同的對(duì)象。而且指針無需在定義時(shí)就對(duì)它初始化,它跟其它內(nèi)置類型一樣,如果沒有初始化,也將擁有一個(gè)不確定的值。

定義指針時(shí)類型的方法將聲明符寫成*d的形式,其中d是變量名,如果在一條語句中定義了幾個(gè)指針變量,每個(gè)變量名之前必須有*。

    int* i1, * i2;//i1和i2都是int類型的指針
	int d, * d1;//d是int對(duì)象,d1是指向int類型的指針

2.2獲取對(duì)象的地址

指針是存放對(duì)象的地址,要想獲取某個(gè)對(duì)象的地址,需要使用 &(取地址操作符)

	int i = 10;
	int* pi = &i;//pi存放變量的i的地址,或者說pi是指向變量i的指針

 注意:指針也是有大小的,它的大小根據(jù)在不同的平臺(tái)是不同的,與指針的類型無關(guān)。

指針的大小在32位平臺(tái)是4個(gè)字節(jié),在64位平臺(tái)是8個(gè)字節(jié)。

在32位機(jī)器上,不管是int,char,double等內(nèi)置類型,或者自定義類型,指針的大小永遠(yuǎn)都是4個(gè)字節(jié)。

除了特殊情況(下面會(huì)講),指針的類型都要和它所指向的對(duì)象嚴(yán)格匹配。

 
	double d;
	double* pd = &d;//正確:pd是指向double對(duì)象的指針
	int* pi1 = &d;//錯(cuò)誤:試圖將double對(duì)象的地址給int類型的指針
    pi1=pd;//錯(cuò)誤:指針pd和pi1的類型不匹配

2.3利用指針訪問對(duì)象

如果指針指向了一個(gè)對(duì)象,那么想要通過指針訪問對(duì)象,需要使用操作符 *(解引用操作符)

	int i = 10;
	int* pi = &i;//pi存放變量的i的地址,或者說pi是指向變量i的指針
 
	*pi = 20;//將i的值修改為20
	cout << *pi << endl;//輸出的是i對(duì)象輸出20

如上述,為*pi賦值實(shí)際上是為p所指的對(duì)象賦值。

注意:解引用僅適合那些確實(shí)指向某個(gè)對(duì)象的有效指針。

2.3空指針

空指針不指向任何對(duì)象,在使用一個(gè)指針之前,需要檢查該指針是否為空指針。生成空指針的方法:

	int* p1 = nullptr;//等價(jià)于int *p1=0;
	int* p2 = 0;//直接將p2初始化為字面常量0
	//需要先#inclde cstdlib
	int* p3 = NULL;

把int變量直接賦給指針是錯(cuò)誤的操作,即使int變量恰好等于0也不可以。

	int zero = 0;
	int* p4 = zero;//錯(cuò)誤:不能將int變量賦值給指針

2.4野指針

2.4.1概念:

野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒有明確限制的)

訪問野指針,相當(dāng)于去訪問一個(gè)本不存在的位置上本不存在的對(duì)象。

2.4.2野指針的產(chǎn)生:

	int* p1;//指針沒有初始化
	int arr[5] = { 0 };
	arr[5] = 11;//指針的越界訪問
	int* ptr = (int*)malloc(sizeof(int));
	free(ptr);//指針指向的空間被釋放

1.指針未初始化:

上訴中的p1是沒有初始化的指針,它沒有指向的空間,但它所占的內(nèi)容將被看作一個(gè)地址值,糟糕的是,如果指針?biāo)嫉目臻g恰好有內(nèi)容,而這些內(nèi)容恰好被當(dāng)作一個(gè)地址,那么我們很難分清它到底是合法還是非法的。所以 建議初始化所有指針,如果不知道不清楚指針指向何處,就把它初始化為空指針。

2.指針的越界訪問:

當(dāng)指針指向的范圍超出數(shù)組 arr 的范圍時(shí), p 就是野指針 ,當(dāng)我們定義只能存儲(chǔ)5個(gè)int類型的空間的數(shù)組,假設(shè)我們要去訪問數(shù)組的第6個(gè)位置。由于第6個(gè)位置的空間沒有定義出來,是未知的。所以arr[5]就是野指針。

3. 指針指向的空間釋放:

當(dāng)我們?nèi)alloc一塊空間時(shí),就會(huì)返回這個(gè)空間的指針去管理這塊空間,當(dāng)這塊空間釋放(銷毀)掉時(shí),但指針依然還在,指針指向的空間就未知的,就為野指針,所以我們釋放一塊空間時(shí),我們需要把指針置為空,如ptr=nullptr。

2.5各個(gè)指針類型的含義

我們知道指針也有不同的類型,對(duì)于指針來說,指針的大小只和平臺(tái)有關(guān),相同平臺(tái)下指針的大小都是一樣的,那么指針的含義是什么?

	int n = 10;
	char* pc = (char*)&n;//pc為char類型的指針,但它指向n
	int* pi = &n;//pi為int類型的指針,指向n
 
	printf("%p\n", &n);//輸出結(jié)果:012FF7E0
	printf("%p\n", pc);//輸出結(jié)果:012FF7E0
	printf("%p\n", pc + 1);//輸出結(jié)果:012FF7E1
	printf("%p\n", pi);//輸出結(jié)果:012FF7E0
	printf("%p\n", pi + 1);//輸出結(jié)果:012FF7E4

注意:%p是打印地址的符號(hào),一個(gè)字節(jié)給一個(gè)對(duì)應(yīng)的地址。

我們可以看出char類型的指針加1是走一個(gè)字節(jié)的距離,int類型的指針加1是走4個(gè)字節(jié)的距離。

同樣的double類型的指針加1是走8個(gè)字節(jié)的距離。

總結(jié):指針的類型決定了指針向前或者向后走一步有多大(距離)。

 //11223344是16進(jìn)制數(shù)字,0x是16進(jìn)制的標(biāo)識(shí)符,每兩個(gè)數(shù)字是一個(gè)字節(jié)
 int n = 0x11223344;
 char *pc = (char *)&n;//pc為char類型的指針,指向n
 int *pi = &n;//pi為int類型指針,指向n
 *pc = 0;   //i變?yōu)?x11223300
 *pi = 0;   //i變?yōu)?x00000000

pi和pc存放的都是n的地址,pc是char類型的指針,通過pc訪問n的時(shí)候只能訪問1個(gè)字節(jié),所以*pc只改變一個(gè)字節(jié)的數(shù)值,pi是int類型的指針,通過pi訪問n的時(shí)候只能訪問4個(gè)字節(jié),所以*pc改變4個(gè)字節(jié)的數(shù)值.

總結(jié):指針的類型決定了指針能夠訪問對(duì)象有多少個(gè)字節(jié)的空間。

2.6 void* 指針

void*指針是一種特殊類型的指針,它可存放任意類型的指針.但我們無法確定對(duì)該地址中到底是個(gè)什么類型的對(duì)象。所以我們不能直接操作void*指針?biāo)傅膶?duì)象。

	double d;
	void* pv = &d;//正確,d可以是任意類型的對(duì)象

利用void*指針能做的事比較有限,拿它和別的指針比較、作為函數(shù)的輸入或輸出或者賦給另外一個(gè)void*指針。

2.7指向指針的指針

指針是內(nèi)存中的對(duì)象,同樣指針也有地址,因此,允許把指針的地址在存放到另一個(gè)指針中。

  通過*的個(gè)數(shù)可以區(qū)別指針的級(jí)別,例如 **表示指向指針的指針,***表示指向指針的指針指針。

	int i = 0;
	int* pi = &i;
	int** ppi = &pi;//ppi指向pi的指針
	*ppi;//*ppi等于pi
	**ppi = 10;//**pi等于i

2.8指針與const

指向常量的指針不能用于改變它所指向的值,要想存放常量對(duì)象的地址,只能使用指向常量的指針

	const int i = 10;
	int* pi = &i;//錯(cuò)誤:pi是一個(gè)普通的指針
	const int* pi1 = &i;//正確:pi1是一個(gè)指向常量的指針
	*pi1 = 20;//錯(cuò)誤:pi1指向的值不能修改

允許另一個(gè)指向常量的指針指向一個(gè)非常量對(duì)象:

	int i1 = 10;
	pi1 = &i1;//正確:但不能通過pi1修改i1的值

指針是對(duì)象,所以允許指針本身定為常量,不能被修改,而且常量指針必須初始化,把const放在*之后,則說明指針是一個(gè)常量指針,常量指針不變的是指針本身,不是指針指向的值不能改變。

	int i2 = 0;
    int i3-10;
	int* const pi2 = &i2;//pi2一直指向i2
    pi2=&i3;//錯(cuò)誤:pi2是一個(gè)常量指針   
    *pi2=12;//正確:pi2指向的值可以被修改
	const double d = 1.111;
	const double* const pd = &d;//pd是一個(gè)指向常量的常量指針
    *pd=2.22;//錯(cuò)誤:pd指向的值不能被修改

 const在*之前是修飾指針指向的值,即指針指向的值不能被修改,const在*之后是修飾指針本身,即指針不能被修改。

3.指針和引用的區(qū)別

1.指針就是一個(gè)對(duì)象,允許對(duì)指針賦值和拷貝,引用是給對(duì)象多起一個(gè)名字,不創(chuàng)建對(duì)象。

2.指針定義時(shí)可以不初始化,引用定義時(shí)必須初始化。

3.引用初始化完成后,引用將和它綁定的初始值一直綁定在一起。指針可以先后指向幾個(gè)不同的對(duì)象。

4.有多級(jí)指針,但沒有多級(jí)引用。

5. 引用自加即引用的實(shí)體增加1,指針自加即指針向后偏移一個(gè)類型的大小

總結(jié)

到此這篇關(guān)于c++基礎(chǔ)學(xué)習(xí)之如何區(qū)分引用和指針的文章就介紹到這了,更多相關(guān)c++區(qū)分引用和指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論