为什么高级语言传参多将实参复制给形参?跟编译有没有关系?
传参有2种常见的实现方式,复制值和复制地址。根据实参的类型,复制值的方式又可分为值传递和引用传递两种。具体来说,如果实参是一个指针,那么就相当于按引用传递,如果实参是非指针类型,就相当于值传递。但两者情况都属于值复制类型。
复制值
复制地址
值传递
引用传递
采用值复制可以满足绝大多数需求。与复制地址相比,只有一点它无法实现,即它无法改变实参。但好处是更加安全和高效,因为在函数中需要改变实参的情况非常少。如果真的有这种需求,通常也可以借助其他手段实现。
安全性就不必说了,因为值复制方式无法改变实参,所以自然是安全的。
下面来说说效率,例如有以下代码:
int a = 5; int b = 6; int c = func(a, b);
在func函数内部,我们可能需要多次使用a和b的值,采用值复制的方式,每次用到参数的值时只需一次寻址(直接向形参执行读或写操作)。如果采用复制地址的方式,此时的形参相当于实参的地址(&a、&b),因此每次读或写操作都要两次寻址:*a先找到实参a,然后向实参执行读或写操作。由于多了一次寻址效率自然变低了。
func
a
b
&a
&b
*a
如果要通过值复制实现地址复制的效果,通常也是有办法的(Java等语言没有指针,因此无法实现)。例如,对于C,可以这样:
int a = 5; int b = 6; int* pa = &a; int* pb = &b; int c = func(pa, pb);
当然,这时还要对func函数进行修改。
有些语言,例如VB、C#,本身就提供了复制地址传递的机制(ByRef、ref),只要给参数加上ref或ByRef关键字,就表示传递的是实参的地址,此时编译器就会将实参的地址复制给形参了。
ByRef
ref
或者传变量指针
基本类型是这样的吧。
阿婆主可以看看函数调用以及栈帧结构就明白了。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
暂无简介
文章 0 评论 0
接受
发布评论
评论(3)
传参有2种常见的实现方式,
复制值
和复制地址
。根据实参的类型,复制值的方式又可分为值传递
和引用传递
两种。具体来说,如果实参是一个指针,那么就相当于按引用传递,如果实参是非指针类型,就相当于值传递。但两者情况都属于值复制类型。采用值复制可以满足绝大多数需求。与复制地址相比,只有一点它无法实现,即它无法改变实参。但好处是更加安全和高效,因为在函数中需要改变实参的情况非常少。如果真的有这种需求,通常也可以借助其他手段实现。
安全性就不必说了,因为值复制方式无法改变实参,所以自然是安全的。
下面来说说效率,例如有以下代码:
在
func
函数内部,我们可能需要多次使用a
和b
的值,采用值复制的方式,每次用到参数的值时只需一次寻址(直接向形参执行读或写操作)。如果采用复制地址的方式,此时的形参相当于实参的地址(&a
、&b
),因此每次读或写操作都要两次寻址:*a
先找到实参a
,然后向实参执行读或写操作。由于多了一次寻址效率自然变低了。如果要通过值复制实现地址复制的效果,通常也是有办法的(Java等语言没有指针,因此无法实现)。例如,对于C,可以这样:
当然,这时还要对
func
函数进行修改。有些语言,例如VB、C#,本身就提供了复制地址传递的机制(
ByRef
、ref
),只要给参数加上ref
或ByRef
关键字,就表示传递的是实参的地址,此时编译器就会将实参的地址复制给形参了。或者传变量指针
基本类型是这样的吧。
阿婆主可以看看函数调用以及栈帧结构就明白了。