指標是c++的乙個非常強大的特性,它能使我們直接訪問計算機的記憶體,指標可以用來引用乙個陣列,乙個字串,乙個整數或者任何其他變數。這種強大的功能使得指標在c++程式設計中是非常普遍的,而同時,指標的知識又顯得有那麼些「繁雜」,有必要清晰地做個總結。
指標,就是記憶體位址。我們一般會宣告乙個變數是整數int
,浮點double
,或者字元char
等等,指標變數(通常簡稱指標)和他們本質上沒什麼區別,不過它儲存的是乙個記憶體位址。
先來看看指標變數的宣告:
int
*pvalue; //
int*pvalue與int* pvalue是一樣的,找一種適合自己的寫法就好
宣告指標變數,要在變數名前方乙個*
,這裡的int
表示這個指標(也就是記憶體位址)所儲存的變數的型別。注意,記憶體位址本身可以理解為是沒有資料型別的,所以指標宣告中的型別完全依賴於所賦值的記憶體位址儲存的資料的型別。比如下面的**,我將指標變數pvalue
的宣告和初始化放一起了:
int
value = 10;
int *pvalue = &value;
需要注意的是第二行,&value
中的&
是取址運算子,表示將已經定義的變數value
所在的記憶體位址賦值給指標變數pvalue
。
int value = 10;
int *pvalue = &value;
std::cout
<< pvalue << std::endl; // 指標的值,0x7fff5e9f4b28
std::cout
<< *pvalue << std::endl; // 指標所指向(即相應的記憶體位址所儲存)的值,10
std::cout
<< &value << std::endl; // 變數value所在的記憶體位址的值,0x7fff5e9f4b28
需要注意的是第3行中,*
此時的作用是「間接引用」,表示讀取指標pvalue
所儲存的變數。*
也叫「間接引用運算子」,和之前在指標變數宣告中*
的作用是不一樣的。這裡大家一定要小心*pvalue
並非指標,pvalue
才是,比如給指標賦值的時候,下面的語法才是對的:
int
value = 10;
int *pvalue;
pvalue = &value; // 這是對的,而*pvalue = &value是錯的
現在,已經知道*
在c++中的3中使用方式:
上面對於*
的總結,也是提醒大家,當看到*pvalue
這種形式時,先要判斷到底是指標的宣告還是間接引用。另外需要注意的一點是,不能像宣告整型變數那樣,用一條語句宣告2個指標。比如:
int i, j; // 一條語句宣告2個整型變數i, j
int *pvalue1,pvalue2; //這條語句實際上宣告了指標pvalue1,和整型資料pvalue2,而pvalue2不是指標
指標也可以作為實參傳遞給函式。c++中,向函式傳遞實參一共有三種方式:按值傳遞;按引用傳遞;按指標傳遞。我在這裡順帶一併總結了。
宣告並定義函式:
#include
void swap(int a, int b)
int main()
實參a, b
直接以數值的形式傳入函式。這個程式執行的結果:a = 1, b = 0
. 可見a和b的值只是在函式內部發生了交換,換句話說,這裡傳入函式的是實參的拷貝,而並未改變實參本身。拿上面的例子來說,想要「徹底」實現兩個數的交換,就要用到「按引用傳遞」的方式了。
引用變數的語法形式為& + 變數名
,此處與取址運算子形式上很像,要注意區分。所謂引用就是引數的別名。如果宣告的函式中形參是引用,那麼形參就是原變數的別名,而並非是拷貝:
#include
void swap(int &n1, int &n2)
int main()
函式第11行,實參a和b實際上分別與形參n1, n2
形成了「共享」。此時的n1, n2
你可以理解為就是a,b的別名。上面程式執行的結果:a = 0, b = 1
.
顧名思義,形參為指標,而傳入的實參也是指標。還是上面的例子:
#include
void swap(int
*n1, int
*n2)
int main()
將整型變數a,b的位址&a, &b
作為實參傳入函式,而函式swap
的實際作用是交換這兩個位址所儲存的數值。形象的說,以前n1
房子住1,n2
房子住0;現在反了,n2
房子住1,n1
房子住0;a和b的值自然也就跟著變化。這個程式的執行結果:a = 0, b = 1
.
此外,我也在這裡對&
符號的應用做個小結:
c++中,陣列就是指標。比如我定義乙個陣列int a =
,那麼陣列變數a
實際上是陣列中元素a[0]
的位址(即a = &a[0]
)。不信我們看看:
int a = ;
std::cout
<< a << std::endl; // 0x7fff5c163b4c
std::cout
<< &a[0] << std::endl; // 0x7fff5c163b4c
這一點是所有指標和陣列問題的核心,明白了這一點,其他好多內容都可以自己推導出來。
比如,可以由陣列變數得到其中某個元素的位址。對於整型陣列a來說,a[i]
的位址是a + i
。
還是上面的例子,我向訪問a[1]
,可以這樣做:
int a = ;
std::cout
<< *(a + 1) << std::endl; // 2
根據這樣的規則,你告訴我*a + 1
是多少,*(a + 1)
又是多少?顯然,這兩個表示式是不一樣的,*a + 1
表示a[0] + 1
的值,而*(a + 1)
則表示a[1]
的值。
此外,我們知道c++函式中不能把陣列當做返回值,但是陣列和指標的性質則可以幫助我們設計返回值是指標的函式,使得其返回的其實就是陣列。不過需要注意的是,一旦陣列宣告,陣列的位置(指標)就不能變了,也就是說陣列其實是「常量指標」。
常量指標有3種形式:
把握一點,const在誰前頭,誰就被定義為常量了。
動態記憶體分配的目的是給變數分配更持久的記憶體空間。我們都知道,在函式中定義的變數是區域性變數,當函式執行完畢,那麼呼叫棧中的區域性變數也就被丟棄了。而有時,可能這個變數還是有用的。為了處理這種情況,可以使用動態記憶體分配。動態記憶體分配是以關鍵字new
實現的。比如:
int *pvalue = new
int
這裡,給指標pvalue
所指向的整型資料分配了記憶體空間。再比如,也可以為陣列分配記憶體:
int *list = new
int[10]
當然,為陣列動態記憶體分配還有乙個好處,那就是可以建立動態陣列(即陣列的長度可以是變數)。動態陣列是個非常有用的概念,比如,我現在要做這樣一件事情:設計乙個函式,函式的輸入為斐波那契數列的長度,返回斐波那契數列的所有元素。**如下:
#include
int *fibonacci(int num)
return
list;
}int main()
return
0;}
可以看到,在第4行建立的動態陣列,這種動態記憶體分配後的永久性也保證了,指標list
的正確返回。
好了,至此指標的基本知識算是介紹完了(之後,我覺得有沒有介紹的重要知識的話,本文還會持續更新)。在實際編碼的過程中,指標的應用是千變萬化的,但是無論怎樣變化,掌握最基本的知識,再做高層次的推理總是沒有問題的。
C 指標的應用
一 指標與陣列 首先看一段程式,來了解陣列名與指標之間的用法。include opencv.hpp using namespace std using namespace cv int main int aptr a for int i 0 i 3 i waitkey 0 return 0 輸出結果...
C 指標應用
int main char str1 hello world char str2 hello world char str3 hello world char str4 hello world if str1 str2 printf str1and str2 are same n else prin...
C 快慢指標的應用
快慢指標的應用 1 判斷單鏈表是否存在環 如果鍊錶是乙個環,就好像操場的跑道是乙個環一樣,此時快慢指標都從煉表頭開始遍歷,快指標每次向前移動兩個位置,慢指標每次向前移動乙個位置 如果快指標到達null,說明鍊錶以null為結尾,沒有環。如果快指標追上慢指標,則表示有環。如下 bool hascirc...