学习笔记六:函数-值传递和地址传递的分析

1.首先,我们要明白执行函数时,编译器对参数以及返回值的处理。编译器会给每个函数参数创建一个临时副本;对于函数返回值,编译器在执行return语句时,会创建一个临时副本,并将该副本放入缓冲区中。
2.下面我们将结合图和代码演示来分析函数在“值传递“和”地址传递“时,发生的动作。
值传递
我们给出这样一段代码片段:

int byvalue(int temp)
{
    temp++;
    int temp01 = 0;
    temp01++;
    return temp01;
}
int main()
{
    int a = 2;
    int b = 2;
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    b = byvalue(a);
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    return 0;
}

我们按照1中知识,我们知道在执行byvalue函数时,编译器会创建参数temp的一个临时副本_temp,在函数体内一切对temp的操作,其实都是对其临时副本_temp的操作。所以对于操作”temp++”其实是”_temp++”,修改的是_temp的值,而temp的值不变,我们可用图1形象表示。

图1

那么,对于返回值呢?又是怎样的情况呢。
同样,从1中我们知道,在执行return temp01时,函数会创建temp01的副本_temp01并将_temp01存在缓冲区中,并且在离开函数作用域后,temp01的生命周期结束,内存被释放,但缓冲区中的_temp01还存在着,如图2所示。

图2

执行上述代码片段,实参a的值在执行byvalue函数之后不会改变,但函数返回值会赋值给b,b会改变。我们可以得到以下结果:

图3

所以函数”值传递“并不会改变实参,但是对返回值却是有效的。

地址传递
同样,我们也给出一段代码,并对代码进行分析。

int* bypointer(int *p)
{
        //注意*p++和(*p)++的区别,前者是指针自增1后,取指向值;后者是取p指向的值,并该值自增1
    (*p)++; 
    int temp01 = 1;
    temp01++;
    int *q = &temp01;
    return q;
}

int main()
{
    int a = 1;
    int *a_p = &a;
    cout << *a_p << endl;
    int *b_p;
    b_p = bypointer(a_p);
    //byvalue(a);
    cout << *a_p << endl;
    cout << *b_p << endl;
    return 0;
}

对于指针传递,我们同样可以按照值传递的思路分析。首先,在执行函数bypointer()函数时,函数会给指针p一个临时副本_p。我们可以知道指针中存的是某段内存的地址,所以我们知道p和_p中有相同的值,是同一内存段的首地址,即p和_p指向同一内存。在bypointer函数体内执行(*p)++,也就是(*_p)++,不过p和_p指向同一内存,*p和*_p指代同一变量,所以(*p)也确实自增了1,如图4所示。

图4

对于”指针传递“的返回值,这里我们需要考虑两种情况:1)指针指向栈内存;2)指针指向非栈内存(堆、全局或静态存储区、常量存储区)
同”值传递“返回值一样分析:
在执行return q;语句时,创建指针q的副本_q,并存在缓冲区中。但若q指向的是栈内存的话,在函数结束后,这块内存会被释放,_q也就成为指向垃圾内存的野指针,自然将其赋值给b_q后,b_q也是指向垃圾内存的野指针,示意如图5所示。

图5

执行上述代码片段,指针a_p指向的值在执行byvalue函数之后会改变,但函数返回的指针指向的栈内存已被释放,故b_p指向的值为垃圾值。我们可以得到以下结果:

图6

所以,函数返回值不能是指向”栈内存“的指针,但可以是指向”堆内存“的指针,因为函数结束时,编译器不会自动释放堆内存。(注意char *p = “hello world!”,这里的p是指向常量内存区的指针,函数返回这样的指针也是可以的,不过返回的始终是一个只读的内存块。)
Note:栈内存中的变量通常是局部变量、函数参数等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值