`
foreversunyao
  • 浏览: 214048 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

传值与传地址的区别---转载

 
阅读更多


2008-11-16 10:39
传值, 
是把实参的值赋值给行参 
那么对行参的修改,不会影响实参的值 

传地址 
是传值的一种特殊方式,只是他传递的是地址,不是普通的如int 
那么传地址以后,实参和行参都指向同一个对象 

传引用 
真正的以地址的方式传递参数 
传递以后,行参和实参都是同一个对象,只是他们名字不同而已 
对行参的修改将影响实参的值
-----------------------------------------------------------------------------------
觉得从函数调用的角度理解比较好 

传值: 
函数参数压栈的是参数的副本。 
任何的修改是在副本上作用,没有作用在原来的变量上。 

传指针: 
压栈的是指针变量的副本。 
当你对指针解指针操作时,其值是指向原来的那个变量,所以对原来变量操作。 

传引用: 
压栈的是引用的副本。由于引用是指向某个变量的,对引用的操作其实就是对他指向的变量的操作。(作用和传指针一样,只是引用少了解指针的草纸)
-----------------------------------------------------------------------------------
函数参数传递机制的基本理论 
  函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数。 
  值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。 
  引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的 
实参变量。  
-----------------------------------------------------------------------------------

仅讨论一下值传递和引用: 
所谓值传递,就是说仅将对象的值传递给目标对象,就相当于copy;系统将为目标对象重新开辟一个完全相同的内存空间。 
所谓引用,就是说将对象在内存中的地址传递给目标对象,就相当于使目标对象和原始对象对应同一个内存存储空间。此时,如果对目标对象进行修改,内存中的数据也会改变。

参数传值与传址
2008年11月11日 星期二 10:52 A.M.

参数是调用函数的代码,传给函数的数据,在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;

分享到:
评论

相关推荐

    传值传名传地址.zip

    常见的参数传递方式有三种:传值、传名和传地址。这三种方式各有特点,理解它们的异同对于编写高效、可控的代码至关重要。 首先,我们来看**传值**。传值是指在调用函数时,将实参的副本(而非实参本身)传递给形参...

    传值与传地址[文].pdf

    在编程语言中,传值与传地址是两种不同的参数传递方式。Java 作为一门面向对象的语言,对于简单类型和对象类型的处理方式有所不同。本文将详细解释这两种类型在Java中的传递机制。 1. 简单类型(按值传递) Java中...

    JAVA传值与传引用[整理].pdf

    JAVA传值与传引用[整理].pdf

    java的传值与传值后的改变

    3. **传值与传引用的区别**: - 原始类型传值时,函数内部的操作不会影响到外部变量。 - 引用类型传值时,函数可以修改对象的内容,但不能改变对象的引用。 4. **局部变量与成员变量**: 函数内部的变量是局部...

    java中传值与传引用

    在Java编程语言中,函数调用时的参数传递方式有两种:传值(Passing by Value)和传引用(Passing by Reference)。虽然Java官方文档中并未明确指出有传引用这一概念,但在实际操作中,Java的行为类似于传引用,尤其...

    在WinForms程序里实现窗体传值的最佳实践 - ver 1.0

    在WinForms程序里实现窗体传值的最佳实践 http://topic.csdn.net/u/20110407/19/c1068d69-7331-4d02-bc0b-f5ba7a5f8dd8.html

    winform跨窗体传值

    在Windows Forms(Winform)应用程序开发中,"跨窗体传值"是一个常见的需求,它涉及到在多个窗体之间共享和传递数据。当你在设计一个包含多个交互窗口的应用时,可能会遇到从一个窗体(Form)传递信息到另一个窗体的...

    传值和传引用-综合文档

    与传值不同,传引用是将变量的地址,而非其值,传递给函数。这意味着函数可以直接操作原始变量,而不是其副本。在LabVIEW中,如果一个VI接受的是一个引用类型的数据,如数组或簇,那么它实际上是在操作这些数据的...

    Swift-传值方式-冉叔叔

    2. 结构体与枚举的传值 结构体和枚举属于值类型。这意味着每当它们被赋值给新变量或者作为函数参数传递时,都会创建一个新的结构体或枚举实例,而不是共享同一内存空间。这确保了值类型的不可变性,除非显式地声明为...

    php传值和传引用的区别点总结

    与传值不同,传引用并不复制变量的值,而是传递变量的内存地址。这意味着,当函数内部对引用的变量进行操作时,实际上是在操作原始变量。这种机制使得函数内部和外部的变量共享同一个内存空间。 ```php $param2 = 1...

    java中传值还是传引用的的认识

    "java中传值还是传引用的认识" Java 中的参数传递是值传递还是引用传递?这是一个经常引发讨论的问题。在 Java 中,参数传递是按值传递的,也就是说,传递给方法的参数是一个副本,而不是原始值本身。 当一个对象...

    页面传值---ASP.NET之5种全局变量!页面间传值方法!.

    **QueryString** 是一种非常简单的页面传值方式,它通过URL地址携带参数,适用于一些简单且不涉及敏感数据的情况。 - **示例代码:** - 在`a.aspx`页面中: ```csharp private void Button1_Click(object sender,...

    页面传值与后台传值

    在IT行业中,页面传值与后台传值是Web开发中的基础技能,特别是在使用Java进行后端处理时。这里我们将深入探讨这两个概念,并结合标签“jsp”和“json”,阐述它们在实际开发中的应用。 首先,页面传值指的是前端...

    C语言中传值与传指针的介绍与区别

    在C语言中,函数参数的传递主要有两种方式:传值(Pass by Value)和传指针(Pass by Pointer)。这两种方式在处理数据时有显著的差异,了解它们的区别对于编写高效且可控的C语言程序至关重要。 **传值**是C语言中...

    赋值传值,引用传值,指针传值的区别

    构造函数,借助构造函数 解释 【赋值传值】,【引用传值】,【指针传值】

    C#餐饮客户端软件毕业设计代码说明全

    房间设置模块修改房间的时候用到了窗体传值(事件传值--委托) fjaiofosaj-md5加密--二次加密---存密码的时候肯定不能存这个密码 房间设置模块用的是两套增删改查 select update insert delete(删除)--update 搜索...

    JAVA中传值与引用问题

    本文将深入探讨Java中的传值与传引用问题,并通过具体的例子来解析其中的原理。 #### 二、基础知识回顾 在Java中,所有的数据类型可以分为两大类:基本类型(如int, double等)和引用类型(如Object, String等)。...

    解决java enctype multipart form-data文件上传传值问题

    ### 解决Java enctype "multipart/form-data" 文件上传传值问题 在Java Web开发中,处理文件上传是一项常见的任务。特别是当涉及到使用`multipart/form-data`作为表单的编码类型时,这种需求更为突出。本文将深入...

    iOS-UI-故事版属性传值-8-7PerformSegue

    在这个主题“iOS-UI-故事版属性传值-8-7PerformSegue”中,我们将深入探讨如何在故事板中传递属性值,特别是通过`UIStoryboardSegue`来实现这一目标。`UIStoryboardSegue`是iOS中一个关键的概念,它定义了两个...

Global site tag (gtag.js) - Google Analytics