首頁 > 軟體

C++深入講解除參照的特點及與指標的區別

2022-05-21 13:00:48

一.引入

在生活中,我們可能也會給一些同學起外號,以“張磊”同學為例,我們可以叫他“張三石”,當我們叫到這個外號的時候就會自然而然的想到“張磊”同學,”張三石”就是張磊的別名,而參照也可以這樣簡單理解:在語法層面上,參照就是取別名。

二.C++中較為麻煩的運運算元

C++中的 * 和 & 有多重含義,在不同的使用條件下有不同的意思:

*

int *p = &a;   /1.指標
a = a * b;     /2.乘法
*p = 100;      /3.指向

&

int c = a&b;    /1.位運算 轉換為二進位制
int *p = &a;    /2.取地址
int  a = 100;
int & ar = a;   /3.參照

三.參照的定義

參照不是新定義一個變數,而是給已存在變數取了一個別名,編譯器不會為參照變數開闢記憶體空間,它與參照的變數共用同一塊記憶體空間。

格式如下:

型別 & 參照變數名(物件名) = 參照實體

注意這裡的空格是可選的,即

  • &符號與前後均可以有一個空格;如下:int & ra=a;
  • &符號與型別挨著,如下:int& ra=a;
  • &符號與參照名稱挨著,如下:int &ra=a;
int main()
{
int a =100; \定義變數名
int b = a;\將a的值賦給變數
int &c = a;\參照 將c作為a的別名 c11中成為左值參照
return 0;
}

在這裡就是相當於一個實體取了兩個名字分別為a和c,並且在這個空間中不開闢新的空間。

四.參照的特點

  • 定義參照時必須給初始化
  • 沒有空參照
  • 沒有所謂的二級參照
  • 一個變數可以有多個參照(就相當於一個變數有好幾個別名,這是可以的)

說明:

int main()
{
int a = 10;
int& b = a;
int& x;
int& y = NULL;
int&& c = a;
}

總而言之:

參照本身是一個變數,但是這個變數又僅僅是另外一個變數一個別名,它不佔用記憶體空間,它不是指標哦!僅僅是一個別名!

五.對比指標與參照

我們以交換函數為例

使用指標交換兩個整型值:

int my _swap (int*ap, int*bp)
{
	assert(ap != NULL && bp != NULL);
	int tmp = *ap;*ap = *bp;*bp = *ap;
}
int main()
{
	int x = 10, y = 20;
	my_swap{&x,&y);
	cout<< "x = " << x << " y = " << y << endl;
	return 0;
}

使用參照交換兩個指標:

void my_swap (int& a,int& b)
{
	int tmp = a;a = b;
	b = tmp;
}
int main ()
{
	int x = 10, y = 20;my_swap(x,y) ;
	cout << " x = " << x<< " y = " << y << endl;
	return 0;
}

形參為指標時:第一句話一定要斷言,必須判斷空不空;並且在使用指標的時候 我們需要注意:是否為 野指標, 空指標 ,失效指標。

當我們使用參照時,不存在NULL參照,不需要判空,比指標更加安全

所以:能不使用指標就儘量不要使用指標! 

六.參照與指標的區別

1.語法層面的區別

從語法規則上講,指標變數儲存某個範例(變數或物件)的地址;

參照是某個範例的別名。

程式為指標變數分配記憶體區域;而不為參照分配記憶體區域。

int main()
{
	int a = 10;
	int* ip = &a;
	int& b = a;  \b是a的別名 並沒有分配新的空間
}

解除參照是指標使用時要在前加“*”;參照可以直接使用。

int main()
{
	int a = 10;
	int* ip = &a;
	int& b = a;  
	*ip = 100;//對於指標使用加「*」
	b = 200;  //參照不需要「*」
}

指標變數的值可以發生改變,儲存不同範例的地址;

參照在定義時就被初始化,之後無法改變(不能是其他範例的參照)。

int main()
{
	int a = 10,b = 20;
	int* ip = &a;
	ip = &b ;
	int& c = a;
	c = b;   //b的值給c實則是把b的值給a,將a的值改為20
}

指標變數的值可以為空(NULL,nullptr);沒有空參照。

指標變數作為形參時需要測試它的合法性(判空NULL);參照不需要判空。

對指標變數使用"sizeof"得到的是指標變數的大小; 對參照變數使用"sizeof"得到的是變數的大小。

int main()
{
	double dx = 10;
	double* dp = &dx;
	double& a = dx; 
	printf("sizeof(dp):%dn", sizeof(dp));
	printf("sizeof(a):%d", sizeof(a));
}

執行結果:

理論上指標的級數沒有限制;但參照只有一級。

即不存在參照的參照,但可以有指標的指標。

++參照與++指標的效果不一樣。

例如就++操作而言:

int main()
(
	int ar[5] = { 1,2,3,4,5 };
	int* ip = ar; //陣列首元素地址
	int& b = ar[O]; //陣列首元素的別名叫b
	++ip;  //由0下標的地址指向1下標的地址
	++b;  //由0下標指向1下標
}

對參照的操作直接反應到所參照的實體(變數或物件)。對指標變數的操作,會使指標變數指向下一個實體(變數或物件)的地址;而不是改變所指實體(變數或物件)的內容。

int main()
(
	int ar[5] = { 1,2,3,4,5 };
	int* ip = ar; //陣列首元素地址
	int& b = ar[O]; //陣列首元素的別名叫b
	++(*ip); //值由1>>2 
	(*ip)++; //所有表示式結束後 進行++ 
	//有括號 先取ip的值與*結合 然後++為所指之物的++
	int x = *ip++;
	//沒有括號 先將ip的值取出 與*結合 把所指之物取出(此時已與*結合完) 然後將ip取出進行++ ++後的值回寫給ip 將值儲存到x中
	//通過()提高了優先順序
}

不可以對函數中的區域性變數或物件以參照或指標方式返回。

當變數的生存期不受函數的影響時就可以返回地址

2.組合層面的區別

組合層面來講參照就是一個指標,但是參照並不是一個普通的指標是指標的語法槽,也可以看作是常性的指標 。

int main()
{
	int a = 10;
	int* ip = &a;
	int& x = a;
	*ip = 100;
	x = 200;
}

七.參照的其他使用

常參照

常參照實際上是一種萬能參照既可以參照普通變數 ,常數,也可以參照字面常數。

(1)參照普通變數

int main()
{
	int a = 10;
	int & b = a;
    const int& c = a;
    b += 10;
    a += 10;
    c += 10;
    return 0;
}

對於這塊報錯問題:是因為c是不可修改的

(2)參照常數

int main()
{
    int a = 10;
    const int b =20;
    int& x = a;
    int& y = b;  //error 不安全
    const int& y = b; //ok
    const int& z =10; //ok
    return 0;
}

(3)參照字面常數

參照字面常數時,分兩步走,首先定義一個臨時量 去參照臨時量 不是參照真實的字面常數10。

int main()
{
    int a = 10;
    const int& z =10; //ok
    //int tmp =10;
    //const int &z = tmp;
    return 0;
}

陣列參照

在參照陣列時,必須知道陣列的大小

int main()
{
    int a = 10;
    int b = 10;
    int ar[5] = { 1,2,3,4,5 };
    int& x = ar[0];  //ok
    int(&x)[5] = ar; //ok   沒有[5]無法編譯通過
    return 0;
}

指標參照

參照既然就是一個變數,那我同樣也可以給指標變數取一個別名

int main()
{
	int a = 100;
	int *p = &a;
	int * &rp = p;
	cout << a << endl;
	cout << *p << endl;
	cout << *rp << endl; //這裡為什麼要將*放在前面,因為p的型別是 int * 作為一個整體哦!!
	cout << p << endl;
	cout << rp << endl;
	getchar();
	return 0;
}
/*
100
100
100
012FF84C
012FF84C
*/

我們發現這裡的指標變數p和它的參照(別名)rp是完全一樣的。但是由於參照的目的跟指標的目的是類似的,所以一般不需要對指標再起別名了。

到此這篇關於C++深入講解除參照的特點及與指標的區別的文章就介紹到這了,更多相關C++參照內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com