6.4.6 对3种传递的补充

    3种传递方式不只是参数传递,函数返回某个值时也有值传递、指针传递和引用传递3种方式,代码6.9是使用范例。

    代码6.9 函数返回某个值时的3种传递方式ReturnMethods


    <—————————————文件名:example609.cpp——————————————> 01 #include<iostream> 02 using namespace std; 03 int main() 04 { 05 int add(int,int);//add()函数声明 06 int*minus(int,int);//minus()函数声明 07 long&multiply(int,int);//multiply()函数声明 08 int x=2,y=3; 09 int addRes=add(x,y);//add()函数调用,传值返回 10 int*minusRes=minus(x,y);//minus()函数调用,传指针返回 11 long*mul=&multiply(x,y);//multiply()函数调用,传引用返回 12 cout<<"2+3="<<addRes<<endl; 13 cout<<"2-3="<<(*minusRes)<<endl; 14 cout<<"23="<<mul<<endl; 15 delete minusRes;//释放堆内存 16 delete mul;//释放堆内存 17 return 0; 18 19 } 20 int add(int m,int n)//add()函数定义,返回值 21 { 22 int z=m+n; 23 return z; 24 } 25 int*minus(int m,int n)//minus()函数定义,返回指针 26 { 27 int*z=new int;//动态堆内存申请 28 *z=m-n; 29 return z; 30 } 31 long&multiply(int m,int n)//multiply()函数定义,返回引用 32 { 33 long*z=new long;//动态堆内存申请 34 z=mn; 35 return*z; 36 }

    输出结果如下所示。


    2+3=5 2-3=-1 2*3=6

    【代码解析】代码中的3个函数add()、minus()和multiply()分别引用了值传递返回、指针传递返回和引用传递返回,为了便于说明问题,在参数传递上都采用了值传递这种方式。

    对于值传递和指针传递来说,就如图6.2所示,被调用函数将返回的值或指针存储在CPU寄存器或某块内存区域中,然后调用函数访问这块内存区域,进行下一步的处理。根据前面的介绍,知道在函数内创建的变量(包括形参)在函数执行完毕后会被撤销,这些变量对应的内存区域会被收回,此时若返回指向函数中变量的指针是错误的,因为在函数执行完毕后,该内存将变成不可用的垃圾内存。换言之,如果将minus()函数定义如下。


    int*minus(int m,int n) { int k=0; int*z=&k; *z=m-n; return z; }

    程序可能会崩溃,函数minus()执行完毕后,指针z和函数中的变量被撤销,虽然指针z的值(对应内存中的某个地址)已经存储在CPU寄存器或某块内存中,但指针所指的这块内存地址已经被释放掉,访问已经释放的内存会给程序带来致命的问题。

    代码第27和33行,使用动态申请内存能有效解决这一问题,在函数执行完毕后,在函数中创建的变量(包括形参)占用的内存(栈内存)会被释放,但动态申请的堆内存不会被释放,关于栈内存和堆内存的内容请参考本章稍后的介绍。

    引用传递同样涉及这一问题,同样可以通过动态申请内存来解决。在本例中,似乎运用指针传递和引用传递并没有带来多大的好处,但如果要传递的是很大的结构或对象,指针传递或引用传递能节省内存的消耗,提高程序的编译效率。