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