传值与传地址的区别

您所在的位置:网站首页 传值与传址的区别 传值与传地址的区别

传值与传地址的区别

2022-10-14 15:25| 来源: 网络整理| 查看: 265

参数是调用函数的代码,传给函数的数据,在C,C++中,参数有两种传递方式:传值方式(它是程序中最常见的传递参数的方法)和传址方式(函数对参数的操作,将直接改变实参的值)。这两个名词分别指:传递“参数的值”和传递“参数的地址”。

“参数的传递方式”,“参数的传递过程”,方式和过程有何区别?中学时我对前桌的女生“有意思”,想给人家传递点信息,是往她家打个电话呢?还是来个“小纸条”?这就是“传递方式”的不同。我选择了后者。至于传递过程:刚开始时我把纸条裹在她的头发里,下课时假装关心地“喂,你的头发里掉了张纸……”。后来大家熟了,上课时我轻轻动一下她的后背,她就会不自在,然后在一个合适时机,自动把手别过来取走桌沿的纸条……这就是传递过程的不同吧?(以上故事纯属虚构)

程序是在内存里运行的。所以无论参数以哪一种方式传递,都是在内存中“传来传去”。在一个程序运行时,程序会专门为参数开辟一个内存空间,称为“栈”。栈所在内存空间位于整个程序所占内存的顶部(为了直观,我们将地址较小的内存画在示意图顶部,如果依照内存地址由下而上递增规则,则栈区应该在底部),如图:

当程序需要传递参数时,将一个个参数“压入”栈区内存的底部,然后,函数再从栈区一个个读出参数。

如果一个函数需要返回值,那么调用者首先需要在栈区留出一个大小正好可以存储返回值的内存空间,然后再执行参数的入栈操作。

假设有一函数:int AddTwoNum(int n1, int n2)     然后在代码某处调用:

....

int a = 1;

int b = 2;

int c = AddTwoNum(a,b);

当执行上面黑体部分,即调用函数的动作发生时,栈区出现下面的操作:

图中标明为返回值预留的空间大小是4个字节,当然不是每个函数都这个大小。它由函数返回值的数据类型决定,本函数AddTwoNum返回值是int类型,所以为4个字节。其它的a,b参数也是int类型,所以同样各占4字节大小的内存空间。

至于参数是a还是b先入栈,这依编译器而定,大都数编译器采用“从右到左的次序”将参数一个个压入。所以本示意图,参数b被先“压”入在底部,然后才是a。这样就完成了参数的入栈过程。根据前面讲的不同“传递方式”,被实际压入栈的数据也就不同。

一、如果是“传值”,则栈中的a,b就是“复制品”,对二者的操作,仅仅是改变此处栈区的内存,和调用处的实参:a,b毫不关联:

二、而在“传址”方式时,编译器会将调用处的a,b的内存地址写入栈区,并且将函数中所有对该栈区内存的操作,都转向调用处a,b的内存地址。请看:看起来二的图比一要复杂得多。其实实质的区别并不多。

在一图中,传给函数的是a,b的值,即1,2;

在二图中,传给函数的是a,b的地址,即:00129980,00129984。

“参数的传递过程”说到最后,还是和“参数的传递方式”纠缠在一起。我个人认为,在刚开始学习C++时,并不需要--或者甚至就是最好不要--去太纠缠语言内部实现的机制,而重在于运用。下面我们就来举一个使用“传址”方式的例子。

题目是:写一函数,实现将两个整型变量的值互换。

幸好实现它也非常的简单和直观。典型的方法是使用“第三者”你可能感到不解:交换两个变量的值,就让这两个变量自个互换就得了,比如小明有个苹果,小光有个梨子,两人你给我给你就好了啊,要小兵来做什么?

呵,你看吧:

int a = 1, b = 2;

//不要“第三者”的交换(失败)

a = b;

b = a;

好好看看,好好想想吧。当执行交换的第一句:a = b;时,看去工作得不错,a的值确实由1变成了2。然后再下去呢?等轮到b想要得到a的值时,a现在和b其实相等,都是2,结果b=a;后,b的值还是2.没变。

只好让“第三者”插足了……反正程序没有婚姻法。

int a = 1, b =2;

int c ; //“第三者”

//交换开始:

c = a;

a = b;

b = c;



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3