C++指標作為函數引數(詳解版)

2020-07-16 10:04:41
《函數參照傳遞》一節,我們介紹了用作函數形參的參照變數,參照變數其實就是原始變數的別名,該原始變數用作實參。這樣的設計使得函數可以存取原始實參變數,從而允許它更改變數的內容。當為一個變數傳入一個參照形參時,則認為該實參是按參照傳遞的。

按參照傳遞實參還有一種替代方法,那就是使用指標作為函數引數。無可否認,參照變數比指標更容易處理,因為參照變數隱藏了所有的解除參照和間接參照"機制"。但是,程式設計師仍然應該學會使用指標作為函數引數,因為有一些任務,特別是在處理 C 字串時,最好使用指標完成、另外,C++ 庫中還有許多使用指標作為形參的函數。

以下是使用指標形參的函數的定義:
void doubleValue(int *val)
{
    *val *= 2;
}
這個函數的目的是使 val 指向的變數翻倍。當 val 被解除參照時,*= 運算子對 val 指向的變數起作用。該語句可以將地址儲存在 val 中的原始變數乘以 2。當然,當呼叫該函數時,必須使用被翻倍的變數地址作為實參,而不是變數本身作為實參。

以下是一個呼叫 doubleValue 函數的範例:

doubleValue(&number);

該語句使用了地址運算子(&)將 number 的地址傳遞到 val 形參中。函數執行後,number 的內容將被乘以 2。下面的程式演示了該函數的用法:
//This program uses two functions that accept addresses of variables as arguments.
#include <iostream>
using namespace std;
//Function prototypes
void getNumber(int *);
void doubleValue(int *);

int main()
{
    int number;
    //Call getNumber and pass the address of number
    getNumber(&number);
    // Call doubleValue and pass the address of number
    doubleValue(&number);
    // Display the value in number
    cout << "That value doubled is " << number << endl;
    return 0;
}
void getNumber(int *input)
{
    cout << "Enter an integer number: ";
    cin >> *input;
}

void doubleValue(int *val)
{
    *val *= 2;
}
程式輸出結果:

Enter an integer number: 10
That value doubled is 20

此程式有兩個使用指標作為引數的函數。請看以下函數原型:

void getNumber(int *);
void doubleValue(int *);

每一個函數原型都使用符號 int * 來表示該形參是一個指向 int 的指標。與所有其他型別的形參一樣,不需要在原型中指定變數的名稱,但星號(*)則是必需。

getNumber 函數要求使用者輸入一個整數值。以下 cin 語句可以將使用者輸入的值儲存在記憶體中:

cin >> *input;

間接運算子會使使用者輸入的值儲存在 input 指向的變數中,而不是 input 中。

在上面的語句中,使用間接運算子是非常重要的。沒有它,則 cin 會將使用者輸入的值儲存在 input 中,就像該值是一個記憶體地址一樣。如果發生這種情況,則 input 將不再指向 main 函數中的 number 變數。如此一來,對該指標(input)的後續使用即使不會產生災難性的結果,也必然出現錯誤。

當呼叫 getNumber 函數時,函數 main 中 number 變數的地址作為實參傳遞。該函數執行後,使用者輸入的數值將被儲存在 number 中。接下來,呼叫 doubleValue 函數,同樣是將 number 的地址作為實參傳遞,這使得 number 被乘以 2。

指標變數也可以用來接收陣列地址作為實參,此後,無論是下標還是指標符號都可以用來處理陣列的內容。下面的程式演示了這一點:
//This program demonstrates that a pointer may be used as a parameter to accept the address of an array. Either subscript or pointer notation may be used.
#include <iostream>
#include <iomanip>
using namespace std;
// Function prototypes
void getSales(double *sales, int size);
double totalSales(double *sales, int size);

int main()
{
    const int QUARTERS = 4;
    double sales[QUARTERS];

    getSales(sales, QUARTERS);
    cout << setprecision(2);
    cout << fixed << showpoint;
    cout << "The total sales for the year are $";
    cout << totalSales(sales, QUARTERS) << endl;
    return 0;
}
void getSales(double *array, int size)
{
    for (int count = 0; count < size; count++)
    {
        cout << "Enter the sales figure for quarter ";
        cout << (count + 1) << ": ";
        cin >> array[count];
    }
}

double totalSales(double *array, int size)
{
    double sum = 0.0;
    for (int count = 0; count < size; count++)
    {
        sum += *array;
        array++;
    }
    return sum;
}
程式輸出結果:

Enter the sales figure for quarter 1: 10263.98
Enter the sales figure for quarter 2: 12369.69
Enter the sales figure for quarter 3: 11542.13
Enter the sales figure for quarter 4: 14792.06
The total sales for the year are $48967.86

請注意,該程式的 getSales 函數中,即使把形參 array 定義為一個指標,其下標符號仍然可以在 cin 語句中使用:

cin >> array[count];

在 totalSales 函數中,array 還可以與以下語句中的間接運算子一起使用:

sum += *array;

而在接下來的語句中,array 中的地址則可以遞增,以使指向下一個元素:

array++;

上面介紹的兩個語句也可以合併成以下語句:

sum += *array++;

* 運算子將首先解除參照 array,然後 ++ 運算子將使得 array 中的地址遞增。