指標初始化(C++)詳解

2020-07-16 10:04:41
請記住,指標被設計為指向特定資料型別的物件。當使用一個地址初始化指標時,它必須是指標可以指向的一個物件的地址。

例如,下面的 pint 定義是合法的,因為 myValue 是一個整數:

int myValue;
int *pint = & myValue;

以下語句也是合法的,因為 ages 是一個整數陣列:

int ages[20];
int *pint = ages;

但是下面的 pint 定義就是非法的,因為 myFloat 不是 int:

float myFloat;
int *pint = &myFloat; //非法

指標可以與其他相同型別的變數在相同的語句中定義。以下宣告定義了一個整型變數 myValue,然後定義了一個指標 pint,該指標使用 myValue 的地址進行初始化:

int myValue,*pint = &myValue;

下面的語句定義了一個陣列 readings 和一個指標 maker,maker 指標使用了 readings 陣列中第一個元素的地址進行初始化:

double readings[50], *marker = readings;

當然,一個指標只能用已定義物件的地址來初始化。以下語句是非法的,因為使用了一個並不存在的物件地址初始化 pint:

int *pint = &myValue; // 非法
int myValue;

尚未被初始化的區域性指標變數並未儲存一個有效的地址,如果嘗試使用這樣的指標,則將導致執行時錯誤。舊版本 C++ 中的慣例是,將地址 0 分配給當前未指向一個有效記憶體位置的指標。

int *ptrToint = 0;
double *ptrToDouble = 0;

在大多數計算機中,使用者程式不能存取地址為 0 的記憶體,因為它被作業系統資料占用。這使得 0 成為指示無效記憶體位置值的安全選擇。

許多標頭檔案(包括 iostream、fstream 和 cstdlib)定義了一個名為 NULL 的常數,代表指標值 0。因此,假設已經包含了這些標頭檔案之一,那麼上面的程式碼就可以寫成以下形式:

int *ptrToint = NULL;
float *ptrTofloat = NULL;

許多人更喜歡後面這種形式,因為 NUL L被非常清晰地確認代表地址 0,而不是整數 0。無論如何,值為 0 的指標也稱為空指標。C++11 定義了關鍵字 nullptr 來指示一個無效的記憶體地址:

int *ptrToint = nullptr;
double *ptrToDouble = nullptr;

可以使用測試是否相等的運算子 != 和 == 來測試指標 p 是否和 0、NULL 或 nullptr 相等,以確定它是否指向了一個有效的地址,範例如下:

if ( p ! = nullptr ) { // 使用指標 P... }
if ( p != NULL ) { // 使用指標 P"... }
if ( p != 0 ) { // 使用指標 P... }

指標只能在被判斷不為0的情況下使用,所以,以上所有測試都等同於以下測試:

if (p) { // 使用指標 P... }

在 C++ 11 中,在變數定義的末尾放置一對空的大括號 {},即可初始化變數為其預設值。數位型別(例如 int、long 和 double)的預設值是 0,而指標型別的預設值則是 nullptr。因 此,以下定義語句:

int mylnt = 0;
double myDouble = 0.0;
int *ptrToInt = nullptr;

與以下語句是等價的:

int mylnt = 0;
double myDouble = 0.0;
int *ptrToInt = nullptr;

能夠快速檢查指標是否已經分配了一個正確的值,這是很重要的。出於這個理由,指標應該始終被初始化或分配一個緊鄰其定義位置的值。此外,除非指標將離開作用域或程式將終止,否則,不再指向一個有效位置的指標應該分配一個 nullptr 值。