C++中的指針,指針函數和函數指針


指針是C或C++中的一大難題,因此弄懂指針對C和C++的學習有很大的幫助,最近一直在研究指針,因此寫一篇隨筆把心得記錄一下。

簡單來說指針也是一種變量,只不過指針變量所存儲的不是我們直觀上看到的,而是內存中的地址。如:

我聲明了一個整型變量a並初始化為5,聲明一個整型指針變量b,並且把a的地址賦給它,因此如果我們直接輸出b的話就會得到a的地址,而輸出*b就會得到a的值。

注意我的聲明語句, int *b; int說明這是整數類型的變量,而*表明這是一個指針變量,合起來就是b是一個整型指針變量,變量名是b而不是*b.這一點很重要。

因此指針變量的聲明方法為:

1 type *variableName;

type是數據類型,variableName是變量名。

這是很簡單的一個指針變量的例子,復雜一點的話,我們看看另一種類型的指針:指向指針的指針。如:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main() {
 6     int num = 5;
 7     int *a = &num;
 8     int **b = &a;
 9     cout << b << " = " << &a << endl;
10     cout << *b << " = " << a << endl;
11     cout << **b << " = " << *a << endl;
12     return 0;
13 }

 

上例中我先生命了一個int並初始化為5,然后聲明一個指針變量a並把num的地址賦值給它,然后再聲明一個指針變量b並把a的地址賦值給它,分析一下上述程序會輸出什么呢?

首先第一行輸出,b=a的地址,因為我們賦值的時候就是這么賦值的,這很好理解。

第二行輸出num的地址=num的地址,為什么呢?我們看看,a的值是什么?沒錯,是num的地址,那么*b是什么?當然就是a的地址存儲的東西,那是什么呢?不就等於a嗎?

第三行輸出5=5,首先*b = &num, 那么*(*b)不就是&num中存儲的東西嗎?那不正是num,所以輸出5=5。

 

還有一個要點就是數組,數組名本身就是一個指針。

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main() {
 6     int a[5] = {1, 2, 3, 4, 5};
 7     int *b = a;
 8     cout << a << endl;
 9     cout << b << endl;
10     return 0;
11 }

運行程序可以看到輸出兩行一樣的地址。

二維數組稍有不同,不同點在於二維數組本身是一個指針數組:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 int main() {
 6     int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
 7     int (*b)[3] = a;
 8     int *c = a[0];
 9     cout << a << " " << b << endl;
10     cout << *(a + 1)[0] << " " << *(b + 1)[0] << endl;
11     cout << *c << endl;
12     return 0;
13 }

b和c的區別在於b是指針數組,包括了(*b)[0]、(*b)[1]、(*b)[2],而c只是一個指針變量,指向數組a的第一個元素的位置。

如圖所示:(多維數組同理)

然后我們再看看什么是指針函數。指針函數的定義和指針變量差不多,如

1 int func1();      // 聲明一個函數,返回值為int類型
2 int *func2();    // 聲明一個函數,返回值為int類型指針,指向一個int的地址

我們可以看一個例子:

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 
 6 // 指針函數
 7 int *square(int &a) {
 8     int *s = new int;
 9     *s = a * a;
10     return s;
11 }
12 
13 int square1(int &a) {
14     int s1 = a * a;
15     return s1;
16 }
17 
18 int main() {
19     int num = 5;
20     cout << "invoke square:" << endl;
21     cout << *square(num) << endl;    // 可以理解為cout << *s << endl;
22     cout << endl;
23     cout << "invoke square1:" << endl;
24     cout << square1(num) << endl;
25     cout << endl;
26     return 0;
27 }

 

 上述程序會輸出:

invoke square:
25
invoke square1:
25

可以看出,指針函數的用法和指針變量差不多,只不過多了參數(不一定有參數,但函數名后面的括號一定不能漏)
然后我們再看看函數指針,函數指針也是一個指針變量,與普通的指針變量不同的是它指向的是一個函數的地址,如:
#include <iostream>

using namespace std;


// 指針函數
int *square(int &a) {
    int *s = new int;
    *s = a * a;
    return s;
}

int square1(int &a) {
    int s = a * a;
    return s;
}

int main() {
    int num = 5;
    int *(*pSquare)(int &a);
    int (*pSquare1)(int &a);
    pSquare = square;
    pSquare1 = square1;
    cout << "invoke square:" << endl;
    cout << *(*pSquare)(num) << endl;
    cout << endl;
    cout << "invoke square1:" << endl;
    cout << (*pSquare1)(num) << endl;
    cout << endl;
    system("pause");
    return 0;
}

 

對比一下pSquare和pSquare1我們會發現區別,pSquare是一個指向指針的指針,而pSquare1是一個指向函數的指針,所以pSquare與square搭配,pSquare1與square1搭配。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM