1. 程式人生 > >【C++】C++中的引用與指標

【C++】C++中的引用與指標

想必大家對C++中的指標都有所瞭解,但是什麼是引用呢?C++11標準引入了“引用”的新功能。

引用

引用(reference):給物件起了另外一個名字,引用型別引用(refers to)另外一種型別,通過將宣告符寫成&d的形式來定義引用型別,其中d是宣告的變數名:

int val = 1024;
int &d = val;

可以認為變數名就是一個可以操控記憶體的標籤,那麼引用就可以理解為另一個標籤。新定義的標籤和原來的標籤都可以訪問存放在記憶體中的資料。
例如:

#include <iostream>
#include <cmath>
using
namespace std; //宣告 void add(int &a,int b); bool& isZero(float f); int main(){ double dval = 0.1; double &d = dval; d+=0.1; cout << "d is " << d << endl; //使用引用作為函式引數 int val = 20; add(val,5); cout << "val is " << val << endl;
//使用引用作為函式返回值 bool &v = isZero(0.000000004); if(v) cout << "0.000000004 is zero" << endl; else cout << "0.000000004 is not zero" << endl; return 0; } //定義 void add(int &a,int b){ a+=b; } bool& isZero(float f){ bool b = false; if(abs(f) < 0.0000001
) b = true; bool &rb = b; return rb; }

輸出結果為:

d is 0.2
val is 25
0.000000004 is zero


C++官方推薦使用引用以一種更安全的方式向函式傳遞資料和獲取返回值。

可以使用常量引用引用一個常量,
比如:

const int &i = 10;

指標

指標(pointer):是可以指向(point to)另外一種資料型別的資料型別,通過將宣告符寫成*d的形式定義指標,其中d是變數名。
取地址符(&):獲取物件的地址。
解引用符(*):獲取指向所指向的物件。

int v = 10;
int *p = &v;
int **m = &p;

p是一個int型別的指標,指向一個int型別,上面的例子中指向了變數v。
m是一個int*型別的指標,指向一個int*型別,上面的例子中指向了變數p。
這裡說指向某個物件就是指存放某個物件的地址。指標就是指地址,地址就是指標。指標變數就是存放記憶體單元編號的變數,或者說指標變數就是存放記憶體地址的變數。

這張圖片解釋了上面這段程式碼的地址指向問題,變數p存放了變數v的記憶體地址,變數m存放了變數p的記憶體地址。

在判斷某個物件的型別的時候,應該從右向左閱讀(離變數名最近的符號對變數型別有最直接的影響),比如

int ****p;
int ****&r = p;

上面的int ****p;離p最近的是第四個*,所以p是一個指標,剩餘的部分確定該指標指向的型別,第四個*號左邊是int ***,所以指標p指向一個int ***型別。再看變數r,離r最近的是&,所以r是引用,剩餘的部分確定該引用引用的型別,剩餘的是int ****,所以r引用了一個int ****型別的變數。

空指標不指向任何物件,使用字面值NULL表示,c++11標準還提供了字面值nullptr也可以獲得空指標。

void*是一種特殊的指標型別,可用於存放任意物件的地址。一個void*指標存放著一個地址,這一點和其他指標類似。但是不能直接操作void *指標所指的物件,因為並不知道物件到底是什麼型別。如果要使用void *所指的物件,應該使用強制型別轉化。

引用與指標

引用和指標的比較:
1.引用不能引用NULL。
2.一旦引用被初始化引向某一個物件後,它就不能再引向另一個物件。指標可以多次改變指向的物件。
3.引用在建立的時候,必須初始化。指標可以在被建立時不被初始化,可以等需要的時才初始化。
4.引用不是物件,沒有實際的地址。指標是一個物件,有實際的地址。指標不能指向引用(因為引用不是物件)。