指針在函數中的使用也是十分廣泛的。某些情況下,將指針作為函數的參數或函數的返回值會給我們帶來方便。而某些情況下,我們又不得不將指針作為函數的參數或函數的返回值。
指針作為參數
我們在上一章我們已經了解向函數傳遞數組的實質是向函數傳遞數組首元素的地址。我們又知道數組名是一個指向數組首元素的指針常量。所以我們認為,向函數傳遞數組是將指針作為參數的特殊形式。
由于指針可以直接操作內存中的數據,所以它可以用來修改實參。這個功能和引用是類似的。
下面我們來看一段程序,了解指針作為參數時的上述兩個特點:(程序8.6.1)
#include "iostream.h"
void arrayCopy(int *src,int *dest,int size);//復制數組元素
void display(const int *array,int size);//輸出數組元素
int main()
{
int a[]={3,4,5,6,3,1,6};
int b[7];
arrayCopy(a,b,sizeof(a)/sizeof(int));//把數組a的元素依次復制到數組b中
cout <<"The data of array a is:";
display(a,sizeof(a)/sizeof(int));
cout <<"The data of array b is:";
display(b,sizeof(b)/sizeof(int));
return 0;
}
void arrayCopy(int *src,int *dest,int size)
{
for (int i=0;i<size;i++)
{
dest[i]=src[i];//修改了實參數組元素
}
cout <<size <<" data Copied." <<endl;
}
void display(const int *array,int size)//const用來保護指針指向的數據
{
for (int i=0;i<size;i++)
{
cout <<array[i] <<" ";
}
cout <<endl;
}
運行結果:
7 data Copied.
The data of array a is:3 4 5 6 3 1 6
The data of array b is:3 4 5 6 3 1 6
根據arrayCopy函數,不難看出傳遞數組和傳遞指針是完全相同的。而通過指針的間接引用或數組操作,我們可以在函數內實現對實參的修改。這就是arrayCopy函數能夠實現復制功能的原因。
不過,將指針作為函數參數的副作用仍然不容我們忽視。指針和引用雖然都能夠修改實參,但是指針卻更加危險。因為引用僅限于修改某一個確定的實參,而指針卻可以指向內存中的任何一個數據,通過間接引用就能夠在一個函數內修改函數外甚至系統中的數據了。這樣一來,函數的黑盒特性就被破壞了,系統也因此變得不再安全。對于程序員來說,將指針作為函數參數可能把函數內的問題引到函數外面去,使得調試程序變得非常困難。所以,我們要認識到使用指針的兩面性,謹慎對待指針做函數參數。
為了避免指針作為函數參數導致數據被意外修改,我們可以使用const來保護指針指向的數據,如程序8.6.1中的display函數。
指針作為返回值
和別的數據類型一樣,指針也能夠作為函數的一種返回值類型。我們把返回指針的函數稱為指針函數。在某些情況下,函數返回指針可以給我們設計程序帶來方便。而且此時通過間接引用,函數的返回值還可以作為左值。
下面我們來看一段程序,了解函數如何返回指針:(程序8.6.2)
#include "iostream.h"
int * max(int *array,int size);//返回值類型是int *,即整型指針
int main()
{
int array[]={5,3,6,7,2,1,9,10};
cout <<"The Max Number is " <<*max(array,sizeof(array)/sizeof(int)) <<endl;//間接引用返回的指針
return 0;
}
int * max(int *array,int size)//尋找最大值
{
int *max=array;
for (int i=0;i<size;i++)
{
if (array[i]>*max)
max=&array[i];//記錄最大值的地址
}
return max;
}
運行結果:
The Max Number is 10
需要注意的是,返回的指針所指向的數據不能夠是函數內聲明的變量。道理很簡單,我們在第六章已經說明,一個函數一旦運行結束,在函數內聲明的變量就會消失。就好像下課同學們都走了,教室里的某一個座位到底有沒有坐著誰我們無法確定。所以指針函數必須返回一個函數結束運行后仍然有效的地址值。