1. 程式人生 > >【面試常見問題】【C++】指標和引用的區別,有哪些不同點,細細道1

【面試常見問題】【C++】指標和引用的區別,有哪些不同點,細細道1

首先咱們弄清楚複合型別(Compound type)這個概念,因為指標和引用是Compound type中的兩種

引用(reference):

  • 何謂“引用”,這麼說吧,相信每個人都有個乳名,後來等到你升學入職啥的發現乳名B格很Low ! 這時候需要為自己起另外一個名字,這就是引用 ! 是一個過程,引用就是為物件另起了一個名字。                                 先明確一下面這兩個‘“混蛋”!

變數定義

  • 相信不少C++程式設計師模糊著“變數(variable)”和“物件(object)”的概念,變數定義的基本形式:型別說明符(type specifier)/基本資料型別( base type)+ 變數名/宣告符( declarator),比如
  • int sum = 0, value, units_sold = 0; 

最後談一下“何為物件”:

物件是什麼? 資料,錯!  變數的值,還是錯! 變數的地址, 好像接近了一點!  準確的講,物件是記憶體空間,也就是首地址到截止地址那一段!

C++就是這樣,繁瑣,木的辦法啊。。。繼續講下去:引用是這麼運作的,我的乳名叫“唐僧”,引用後呢,“&唐宛如”,WTF,沒錯,新名字前加了個&,你沒看錯,是加了個&,一個嶄新的名字就產生了。。。,比如

int iVal = 2^10;
int &refVal = iVal;  //refVal 就是 iVal 另起的名字了【前面有個&】
int &refVal2;    // 錯!~ 引用必須先初始化 

!引用即別名,引用不是物件呢,他僅僅僅僅僅僅真的真的真的只是一個物件的別名,我乳名叫 iVal , 大名叫 refVal , &表示refVal 是後有的,大名

廢了好大勁,希望讓看的人儘量有個深刻的印象,徹底弄明白這貨,繼續:

引用講明白了,輪到指標(pointer)了,Pointer 破了他,‘point to’,指向某人,指向某物,指向某種型別。這裡看明白沒有,和引用相似在於都實現了對其他人的間接訪問,當面害羞,只好找個中間人送情書;

關鍵來了:指標和引用根本就不是一個世界的,其一:指標本身就是個“人”,引用只是給人起別名,指標可以被賦值和拷貝,引用不得行;指標還可以 耍朋友,厭倦了再換,即指向不同的物件/人,但是每次只能指向一個,腳踏兩條船是不允許滴;其二,指標可以不用賦初值,引用不得行,他一定有個初值,嬰兒和幼兒的區別,嬰兒咕咕墜地,啥都不懂,幼兒都有大名了,你說他吃了多少米了都,經事了。比如

int *p1, *p2; //p1,p2 均指向int型物件
double p3, *p4; //p3位double型物件,p4為指向all double 型物件的指標
int p5 = 1, *p6 = &p5; //p6 指向/存放 p5的地址


末了,總結:

(1)指標:指標是一個變數(variable)/物件(object),只不過這個變數 儲存/指向 記憶體的一個  地址/儲存單元;而引用跟原來的變數實質上是同一個東西,只不過是原變數(variable)/物件(object)一個別名而已。  

(2)可以有const指標,但是沒有const引用;

(3)指標可以有多級,但引用只能是一級(int **p;合法 而 int &&a是不合法的)
(4)指標的值可以為NULL,也可以不用初始化,但引用的值不能為NULL,並且引用在定義之前必須先經過初始化;

(5)指標的值在初始化後可以改變,即指向其它的儲存單元,而引用在進行初始化後就不會再改變了。

(6)"sizeof引用"得到的是原來的變數(物件)的大小,而"sizeof指標"得到的是指標本身(所指儲存單元對應的記憶體地址)的大小;

(7)指標和引用的自增(++)運算意義不一樣;


…^ - ^… 搬磚驗驗又何妨,光說不練,上面看起來在玩文字遊戲,體現不出多少價值。C++語言中,函式的引數和返回值的傳遞方式有三種:值傳遞、指標傳遞和引用傳遞。

  • 值傳遞:下面給出一個“值傳遞”的示例程式。 fun 函式體內的 x 為main 函式中 變數 i1 的一份拷貝,改變 x 的值不會影響 i1, 所以 i1 的值仍然是3,而 x 的值為3+1=4。【這道題實在是常見啊,很容易錯,博主自己也想了好久 -ORZ-】

    #include <iostream>
    //#include <vector>
    using namespace std;
    void fun( int x ){
    	x = x + 1;
    }	
     int main()
    {
    	cout << "請輸入1個整數:" << endl;
    	int i1;
    	cin  >> i1;
    	fun( i1 );
    	cout <<"i1 = " << i1 << endl;
    	system("pause");
    	return 0;
    }
  • 引用傳遞:示例程式如下。 fun 函式體內的 x 為main 函式中 實參i1本身,改變 x 的值將直接 導致 i1變化, 所以 i1 的值仍然是333+1 =334,同樣, x 的值為333+1=334.  由此可見,引用作為函式引數進行傳遞時,實質上傳遞的是實參本身,即傳遞進來的不是實參的一個拷貝,因此對形參的修改其實是對實參的修改,所以用引用進行引數傳遞時,節約時間節約空間!

    #include <iostream>
    //#include <vector>
    using namespace std;
    
    void fun( int &x ){
    	x = x + 1;
    }
    	
     int main()
    {
    	cout << "請輸入1個整數:" << endl;
    	int i1;
    	cin  >> i1;
    	fun( i1 );
    	cout <<"i1 = " << i1 << endl;
    	system("pause");
    	return 0;
    }

指標傳遞:以下是“指標傳遞”的示例程式。fun 函式體內的 x 指向/儲存/存放 main 函式中變數(物件)i1 的地址(儲存單元),改變 指標x 的值(內容) 導致 i1的值(內容)變化, 所以 i1 的值是33+1 =34; x 的值為0x00affb38 {33} -> 0x00affb38 {34}.  

#include <iostream>
//#include <vector>
using namespace std;

void fun( int *x ){
	*x = *x + 1;
}
	
 int main()
{
	cout << "請輸入1個整數:" << endl;
	int i1;
	cin  >> i1;
	fun( &i1 );
	cout <<"i1 = " << i1 << endl;
	system("pause");
	return 0;
}





…^ - ^… 細細咀嚼一下上述三個示例程式,你會覺得“引用傳遞”的性質頗有些類似“指標傳遞”,而書寫方式更加簡潔,只比“值傳遞”多了引用符號,勝在時間和空間。儘管如此,“引用”可以做的任何事情“指標”也都能夠做,那為什麼還要“引用”,就好比家有電動車,貴是貴了點,充電還又麻煩,但是自行車能做的電動車也能做。那麼,“自行車的意義何在?”

我認為,存在即合理,任何東西存在的本質一定有其合理性,用最適當的工具做最恰當的事情;指標就像是一把瑞士軍刀,技術到位,上至橫掃疆場,下至修剪眉毛,關鍵是,不是每個程式設計師都有這個金剛鑽,攬不下瓷器活的嘛,指標功能是強大,可稍微不慎,給自己挖坑走上懸崖邊邊也就分分鐘的事。

    某些場合,只是需要借用某變數(物件)的“別名”,那麼拿出小刀“引用”就可以了,至於牛刀“指標”,還是放一邊晾著的好,以免發生意外。