指针/引用参数

在介绍指针/引用参数之前,先来介绍函数的传递方式。在C++中,函数参数主要采用两种传递方式:值传递和引用传递。所谓值传递是指在调用函数时将实际参数复制一份传递到函数中,这样,在函数中如果对参数进行修改,将不会影响到实际参数;而引用传递是指在调用函数时将实际参数的地址传递到函数中,那么,在函数中对参数所进行的修改,将影响到实际参数。

下面编写一个按值传递的函数OutputNumber,函数的作用是输出一个数值。

例4.2  按值传递。(实例位置:光盘\TM\Instances\4\例4.2)

  1. void OutputNumber(int nNumber)  
  2. {  
  3.     cout << nNumber << endl;    //输出数值  
  4.     nNumber 20;           //修改参数  

在main函数中调用OutputNumber函数。

  1. int main(int argc, charargv[])  
  2. {  
  3.     int nNum 10;      //定义一个变量  
  4.     OutputNumber(nNum); //调用OutputNumber函数  
  5.     cout << nNum << endl;   //输出变量值  
  6.     return 0;  

运行程序,效果如图4.4所示。

从图4.4中可以发现,在OutputNumber函数中输出的数值是10,尽管在该函数中将参数nNumber设置为20,但是在main函数中执行"cout << nNum << endl;"语句时,输出的结果仍为10。因为OutputNumber函数采用按值传递,对形式参数nNumber的修改不会影响到实际参数nNum。

如果修改OutputNumber函数,将参数的类型修改为引用类型,则OutputNumber函数将按引用方式传递。

 
图4.4  值传递

例4.3  按引用传递。(实例位置:光盘\TM\Instances\4\例4.3)

  1. void OutputNumber(int &nNumber) //设置引用类型参数  
  2. {  
  3.     cout << nNumber << endl;                            //输出结果  
  4.     nNumber 20;                                   //修改参数值,将影响到实际参数  
  5. }  
  6. int main(int argc, charargv[])  
  7. {  
  8.     int nNum 10;                                  //定义一个变量  
  9.     OutputNumber(nNum); //调用OutputNumber函数  
  10.     cout << nNum << endl;   //输出变量值  
  11.     return 0;  

运行程序,效果如图4.5所示。

 

 
图4.5  引用传递

 

从图4.5中可以发现,在OutputNumber函数中将形式参数nNumber设置为20,实际参数nNum的值也为20。因为引用传递,传递的是参数的地址,对nNumber的修改自然会影响到nNum。

许多读者可能会问,如何判断函数是值传递还是引用传递呢?这需要根据参数的数据类型来判断,如果参数的数据类型是指针类型、引用类型或数组类型,则函数是引用传递,其他情况下是值传递。因此,不仅只有引用数据类型才是按引用传递,指针和数组类型参数同样是按引用传递。下面修改函数OutputNumber,采用指针作为函数参数。

例4.4  指针作为函数参数。(实例位置:光盘\TM\Instances\4\例4.4)

  1. void OutputNumber(int *pNumber) //使用指针作为函数参数  
  2.     
  3.     cout << *pNumber << endl;      //输出参数值  
  4.     *pNumber 20;                  //设置参数值  
  5. }  
  6. int main(int argc, charargv[])  
  7. {  
  8.     int nNum 10;      //定义一个整型变量  
  9.     OutputNumber(&nNum);    //调用OutputNumber函数  
  10.     cout << nNum << endl;   //输出nNum  
  11.     return 0;  

运行程序,效果与图4.5是相同的。

在编写函数时,如果函数需要采用引用方式传递,使用指针和引用作为参数类型都是可以的。使用指针和引用类型作为函数参数各有优缺点,视具体环境而定。对于引用类型,引用必须被初始化为一个对象,并且不能使它再指向其他对象,因为对引用赋值实际上是对目标对象赋值。这是引用类型的缺点,但也是引用类型的优点,因为在函数调用时需要验证引用参数的合法性。例如,如果函数OutputNumber采用引用参数类型,则语句"OutputNumber(0);"是非法的。如果函数OutputNumber采用指针类型参数,则语句"OutputNumber(0);"是合法的。因为0被认为是一个空指针,对空指针操作必然会导致地址访问错误。因此对于指针对象作为函数参数,函数体中需要验证指针参数是否为空。这是使用指针类型作为函数参数的缺点。但是,使用指针对象作为函数参数,用户可以随意修改指针参数指向的对象,这是引用类型参数所不能的。


---------------------------------------------------------------------------

void f(int *p)和void f(int *&rp)有什么区别?
我知道rp不占内存空间,只是实参的别名,对rp的改变就是对实参的改变。难道指针引用和指针的区别仅仅是一个不占内存一个占内存?

这很好理解,别想多了。
int* 也就是一种类型而已,所以你的问题和 void f2(int p) 与 void f2(int &rp)有什么分别得到的回答是一样的。rp当然要占内存空间,所占空间是一个指针的大小。
简单的来说,比如参数是 int *ptr; 假设其内容为0x12345678,内容指向的值为5,其在内存中的地址为0x00112233;
那么调用第一个f传入的值是0x12345678,第二个传入的是0x00112233。
 
楼上的没说全,你都知道引用是别名,那就应该知道在函数内部可以修改rp指向的地址,以前指向的是a,你可以把他改成指向b;传指针是传入参数的一份拷贝,在函数内部修改指针指向的地址,并不会修改原实参所指向的地址。可以写一个简单的程序测试下,在函数内部修改形参所指向的地址,调用完成后,看看实参指向的地址是否改变!传指针不会改变,传引用的会!动手实验下,记得更劳靠!
 
---------------------------------------------------------------------------
void test1(int * x, int * y)
{
    cout << *x << endl;
    x = y;
    cout << *x << endl;
}
void test2(int * & x, int * y)
{
    cout << *x << endl;
    x = y;
    cout << *x << endl;
}
void test3(int * x, int * y)
{
    cout << x[0] << ' ' << x[1] << endl;
    x = y;
    cout << x[0] << ' ' << x[1] << endl;
}
void test4(int * & x, int * y)
{
    cout << x[0] << ' ' << x[1] << endl;
    x = y;
    cout << x[0] << ' ' << x[1] << endl;
}
int main(int argc, char *argv[])
{
    int *a, *b;
    *a = 1;
    *b = 2;
    test1(a, b);
    cout << *a << endl;
    cout << *b << endl;
    test2(a, b);
    cout << *a << endl;
    cout << *b << endl;
    int *c, *d;
    c = new int[2];
    d = new int[2];
    c[0] = 0;
    c[1] = 1;
    d[0] = 10;
    d[1] = 11;
    test3(c, d);
    cout << c[0] << ' ' << c[1] << endl;
    cout << d[0] << ' ' << d[1] << endl;
    test4(c, d);
    cout << c[0] << ' ' << c[1] << endl;
    cout << d[0] << ' ' << d[1] << endl;
    delete [] c;
    delete [] d;
    return 0;
}
运行结果:

1

2

1

2

1

2

2

2

0 1

10 11

0 1

10 11

0 1

10 11

10 11

10 11



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值