精华内容
下载资源
问答
  • 实参和形参之间信息传递

    千次阅读 2014-09-21 22:31:56
    这种方式是在过程调用代码序列中给出实参的地址 (如果实参是简单变量或下标变量,则在调用代码序列中直接给出其地址;如果实参是常数或表达式,则应产生计算它们之值并存入临时单元中间代码,而在调用代码序列中...
    一、 引用调用(Call by reference)

    这种方式是在过程调用的代码序列中给出实参的地址 (如果实参是简单变量或下标变量,则在调用代码序列中直接给出其地址;如果实参是常数或表达式,则应产生计算它们之值并存入临时单元的中间代码,而在调用代码序列中给出此临时单元的地址等),控制转入被调过程后,由被调过程将实参的地址写入相应的形式单元。过程体中对形式参数的任何引用或赋值,都按对相应形式单元间接访问的寻址方式为其产生代码。显然,按此种方式实现形实结合,执行过程体时,对形参的赋值将会影响相应实参之值。

    二、 值调用(Call by value)
    值调用也是一种经常采用的方式 (PASCAL语言中的值参、C语言中的所有参数等等)。它和引用调用的主要区别在于:进入过程时,送入形式单元的不是相应实参的地址而是它的值;过程体中对形参的任何引用或赋值都是按对形式单元的直接访问来产生代码。因此,一旦把实参之值送入对应形式单元之后,在执行过程体期间,除了以实参之值作为形参的初值进行运算之外,将不再与实参发生任何联系。由此可见,过程执行的结果决不会改变实参之值。


    三结果调用(Call by result)

    这两种方式在某些FORTRAN语言的编译系统中使用。其特点是,为每个形参分配两个形式单元,第一单元用于存放实参的地址 (左值),第二单元用于存放实参的 (右)值 (在结果调用中,实参的值将不被传送),在执行过程体时,将只对第二单元进行操作,但在返回时,将第二单元的内容,按相应的第一单元中的地址传给实参。需注意,在结果调用中,因在进入过程时实参的值未被传送,所以,在过程体中形参的初值是不确定的,因此对形参的第一次访问必须是为其赋值,而不允许使用其值,否则,程序运行的结果将不可预测。


    名字调用(换名调用Call by name)在早期的ALGOL语言中使用,其原理是,将形参视为过程体中的一个宏,形实结合时,将形参在过程体的每个出现,均用实参表达式取而代之,为避免引起运算顺序变化,结合时将自动为实参表达式加上括号。

    展开全文
  • 指针和引用以及实参和形参前言1.当一个类对象作为实参数传递时,使用值传递和引用传递有什么区别?2.参数传递方式分:传值和传址3.关于何时使用引用参数?4.总结:什么时候用指针和引用(二) 前言 本文章为转载,...

    前言

    本文章为转载,转载原链接已失效

    1.当一个类的对象作为实参数传递时,使用值传递和引用传递有什么区别?

    比如: DateType ExampleFun(CString &strFileName,…)与

    DateType ExampleFun(CString strFileName,…)
    解答之前,我们先来看2个基本的概念:形参和实参。
    ->通俗的讲:形参是形式上的参数,实参是实际的参数;
    ->详细的讲:形参只是对实参的一种抽象类型描述,只是声明一个函数(方法)能接受什么类型的实参,而不确定接受的实参具体内容是多少;
    实参就是传递给函数(方法)对应形参的具体内容(值),形参的初始指(内容)由实参决定.形参在函数(方法)结束返回后就被释放了.

    2.参数传递方式分:传值和传址

    1).传值方式,只是将实参的值的拷贝传递给函数(方法),在方法内对形参进行操作,其对象是实参的拷贝,对实参不能造成影响.在方法结束返回后,形参被释放丢弃,实参的内容并不会改变;
    2).传址方式,将实参的地址传递给函数(方法),在方法内对形参进行操作即等于对实参进行相同的操作,在方法结束返回后,形参同样被释放,实参的内容将会是对形参进行操作的结果.
    而传址方式,又可以细分为:引用传递(pass-by-reference) , 指针传递(pass-by-pointer)
    引用其实就是对象的别名,传对象的引用,用于把一个对象的地址作为参数传过去,而不是对象本身。
    这是我们就明白了前面问题的答案:传递引用,避免了一次实参到形参的拷贝,提高了效率。

    3.关于何时使用引用参数?

    (1)使用引用参数的主要原因有:
    程序员能够修改调用函数中的数据对象
    通过传递引用而不是整个数据对象,可以提高运行速度

    (2)对于使用传递的值而不做修改的函数:
    如果数据对象很小,如内置数据对象,则按值传递
    如果数据对象是数组,则使用指针,并将指针声明为指向const的指针
    如果数据对象是较大的结构则使用const指针或const引用,以提高效率,节省复制结构所需的时间和空间
    如果数据对象是类对象则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因,因此传递类对象的标准方式是按照引用传递。

    (3)对于修改调用函数中数据的函数:
    如果数据对象是内置数据类型则使用指针。
    如果数据对象是数组则只能使用指针
    如果数据对象是结构则使用引用或指针
    如果数据对象是类对象则使用引用

    4.总结:

    在c/c++编程中,到底什么时候该用指针来传递参数呢?总结如下:

    1. 需要改变实参的时候, 只能用指针.

    2. 传递大型结构并且"只读"其元素的时候,因为大型结构通过值传递, 需要拷贝其每个元素, 这样效率太低.

    3. 需要遍历数组或频繁引用其元素时, 这样效率比使用下标高.

    4. 动态分配空间时, 必须使用指针.

    5. 传递数组时, 必须使用指针.

    6. 函数返回指针时, 比如fopen

    7. 另外,有时候需要使用二级指针,即指针的指针,例如:

      MemAllocate(char *a){
      a=(char *)malloc(sizeof(char));
      }

    当调用此函数进行内存分配时,发现不能分配内存不能成功,因为此时对于a来说,形参改变了,但实参并不会改变,他们对应于不同的内存单元。正确的写法应该是:

    MemAllocate(char **a){
    *a=(char *)malloc(sizeof(char));
    

    }

    这样就能够正确地分配内存了。

    指针和引用很多时候效果是一样的,但是引用往往会带来阅读上的困难,因为在使用方法上和形参一样,但 是具备指针的特性。再加上 如果数据对象是类对象则使用const引用。类设计的语义常常要求使用引用,这是C++新增这项特性的主要原因,因此传递const类对象的标准方式是按照引用传递。其他时候用指针较好

    什么时候用指针和引用(二)

    首先,要认识到在任何情况下都不能用指向空值的引用。一个引用必须总是指向某些对象。
    1.如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针
    2.如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。
    3.不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。
    引用的一些规则如下:
    (1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化)。
    (2)不能有NULL 引用,引用必须与合法的存储单元关联(指针则可以是NULL)。
    (3)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。

    展开全文
  • 文章目录数据变量分类数据是怎么存的实参形参引用传递和传递传递引用传递结合存储方式做理解特殊情况 数据变量分类 首先,我们需要大概明白,java中数据类型分为两类,基本类型与对象类型(一些特殊...

    数据和变量的分类

    首先,我们需要大概明白,java中的数据类型分为两类,基本类型对象类型(一些特殊的如String后续讨论)

    基本类型:byte,short,int,long,char,float,double,boolean,returnAddress
    对象类型:类类型,接口类型和数组

    以上数据类型是针对数据本身特点而言的,如果我们要使用他们,也就是数据成为了变量,此时结合数据在内存中的保存方式,对应的叫法成为了基本类型引用类型
    基本类型保存的是对象本身的值,而引用类型保存的是引用的值,也就是对象地址的值。

    数据是怎么存的

    数据是怎么存的,其实是个很复杂的话题,需要涉及到很多java内存模型的知识,此处不再深入拓展。从以下场景的代码来简单说明下

    // 首先需要明白,People这个对象实例化就是放在堆中的,所以它里面的成员变量自然也是在堆中的。
    Class People{
    	// age是一个基本类型
    	int age;
    	// child是一个引用类型
    	People child;
    	void setAge(int age){
    		this.age = age;
    	}
    	void setChild(int child){
    		this.child= child;
    	}
    }
    Class People Test(){
    	public void createPeople(){
    		// 这一步只是声明了一个引用类型的变量man,并为他在方法栈中分配了内存空间,用来存放之后对象的地址值
    		People man;
    		// 这一步在内存中创建了一个对象,并将对象的地址值(比如A0X456465之类的)赋值给了man这个引用变量 
    		man = new People()
    		// 这一步是在方法栈中声明了一个基本类型的变量age,并为他分配了内存用来存储数据本身。
    		int age;
    		// 这里的10是存在方法栈中的。
    		age = 10;
    		// 这里将方法区中定义并赋值的基本变量age的值赋值给了引用变量man所指向的对象的成员变量age。所以man.age的值是存在堆中的。
    		man.setAge(age);
    		// 这里将一个堆中对象child的地址值赋值给了man中的引用成员变量child。所以其实man.child与方法中定义的child这两个引用变量,指向的是同一个堆中的对象所在的地址
    		People child = new People;
    		man.setChild(child);
    		
    	}
    }
    

    实参与形参

    // 这里的age是实参
    int age = 10;
    // 方法签名里的就是形参
    setAge(age);
    

    引用传递和值传递

    值传递

    值传递就是实参把它的值传给形参,基本数据类型都是值传递,即函数接受的是实参的一个copy,内存中存在两份参数,也就是两份变量和值,方法中对参数的修改不会影响原本实参的值

    引用传递

    引用传递就是实参把引用传给形参,对象类型都是引用传递,即函数接受的是对象的地址值,内存中存在一份参数,一份变量和值,方法中对参数的修改会影响原本实参的值

    结合存储方式做理解

    其实造成这种区别的原因,结合上面数据的存储方式就很好理解了,不管是那种传递,传递本身的操作是一样的。
    比如我定义了一个变量a,传递给方法test(),就是把这个变量a的值copy一份传给test()。
    只不过当变量a的类型是基本数据类型的时候,a存储的就是值本身,传递的是一份原始值的copy,所以我们在方法中对传进来的a做修改,并不会影响到最初的a。
    当变量a的类型是引用类型的时候,a存储的是引用本身,传的自然是引用的copy,我们在方法中对a做修改的时候,如果是对a指向的对象做修改(比如a.setAge(50)这种操作,这里假设age是一个成员变量),那么由于两个引用指向的是同一块堆中的内存,自然是有影响的。
    如果是a = new A()这种操作,是不会影响到之前的a的,因为它没有对之前堆中对象做修改,只是改变了引用本身的值。

    特殊情况

    对于String、Integer、Double等几个基本类型包装类,都是immutable类型(为了深度拷贝方便),尽管他们是引用类型的变量,但是由于没有提供自身修改的函数,所以每次对对象的修改操作都会形成新的对象,即在堆中开辟新的内存,所以它的效果和值传递是一样的

    展开全文
  • 相关基本概念: 形参:定义方式时写参数为形参 实参:真正调用方法时,传入参数为实参。...在调用过程中,将实参的地址传递给了形参形参改变都发生在实参上。 基本数据类型:有八种 整数类...

    相关的基本概念:

    • 形参:定义方式时写的参数为形参
    • 实参:真正调用方法时,传入的参数为实参。
    • 在我们调用方法时,会把实参传递给形参,方法内部其实是在使用形参。
    • 传值调用:传值调用中传递的参数为基本数据类型,参数视为形参。
    • 传引用调用:传引用调用中,如果传递的参数是引用数据类型,参数视为实参。在调用过程中,将实参的地址传递给了形参,形参上的改变都发生在实参上。
    • 基本数据类型:有八种
    1. 整数类型:long、int 、short、byte
    2. 浮点类型:float、double
    3. 字符类型:char
    4. 布尔类型:boolean
    • 引用数据类型:类、接口类型、数组类型、枚举类型、注解类型、字符串类型

    eg:String类型就是引用类型

    传值调用:

    结果为:

    在通常的学习中经常遇到这个例子:

    public class Test {
       
        //进行的是传值调用,形参的变化不影响实参的数值
        public static void swap(int x,int y){
            int temp=x;
            x=y;
            y=temp;
        }
    
        public static void main(String[] args) {
            int a=10;
            int b=20;
            swap(a,b);
            System.out.println("a="+a+",b="+b);
    
        }
    }
    

    结果为:

             

    数字进行交换,利用值传递根本就没有改变内容;要利用到传引用调用

    当使用基本数据类型作为方法的形参时,在方法体中对形参的修改不会影响到实参的数值

    传引用调用

    public class Test {
    
        //传引用类型参数,形参的变化影响实参的变化
        public static void swap(int [] array){
            int temp=array[0];
            array[0]=array[1];
            array[1]=temp;
        }
    
        public static void main(String[] args) {
            int [] array={10,20};
            swap(array);
            System.out.println("a="+array[0]+",b="+array[1]);
        }
    }
    

    结果为:

    基本数据类型和引用数据类型作为参数的区别:

    • 基本数据类型的变量中直接存放数据值本身,所以改的时候改的是数据值本身;基本数据类型修改形参的话,是不影响实参的。
    • 但是引用数据类型不同的地方在于真正的数据并没有在栈区的变量中保存,而是在堆区里面保存着,虽然拷贝了一份,但是二者
    • 指向的是同一块堆区。引用数据类型修改形参是影响实参的。

    总结:

    1.Java的基本数据类型是传值调用,对象引用类型数传引用。

    2.当传值调用时,改变的是形参的值,并没有改变实参的值,但是实参的值是可以传给形参的,但是,形参的值不能传给实参。

    3.当引用调用时,如果参数是对象,无论对对象做了何种操作,都不会改变改变实参对象的应用(可参考String),但是,如果改变了对象的内容,就会改变实参对象的内容,因为形参变量和实参变量共享一块堆区。

     

    注:参考文章:https://blog.csdn.net/xyphf/article/details/78117027

    展开全文
  • 在主函数实现了解传递的本质。 提示:以下是本篇文章正文内容,下面案例可供参考 一、值传递 在主函数中 #include <iostream> using namespace std; void main() { int i=10; int j=i; j=20; cout<&...
  • Python-06_实参_形参

    2019-03-25 20:33:10
    实参 """ 实参传递方式:argument 位置传参: 序列传参 关键字传参: 字典传参 """ def fun1(a, b, c): print("a=", a) ...# 位置传参: 实参和形参的位置一一对应! fun1(2, 3, 1) # 序列传参:...
  • 文章已移至 C++ 形参和实参在三中传递方式区别
  • C语言中实参和形参之间数据传递是单向“值传递”,单向传递,只能由实参传给形参,反之不行 输出格式并没有选择%p而是选择了%d,因为十进制数看起来更直观 1 值传递 如果只是传递话: #include //值...
  • 形参实参之间传递

    千次阅读 2013-10-09 11:45:20
    C语言中,参数的传递方式是“单向值传递”,形参和实参变量各自有不同的存储单元,被调用函数中的形参变量值的变化不会影响实参变量值。 举个例子  #include  void swap(int x,int y)  {  int z...
  • 形参和实参之间三种传递方式

    千次阅读 2011-11-28 19:39:42
    //形参和实参之间三种传递方式 void fun(int i) { i++;} void fun(int &i) { i++;} void fun(int *i) { *i=*i+1;} 若指针指向是数组首地址,则数组元素访问方式 1.数组名[i] 指针名[i] 2.*...
  • 2.当传值调用时,改变的是形参的值,并没有改变实参的值,实参的值可以传递给形参,但是,这个传递是单向的,形参不能传递实参。 3.当引用调用时,如果参数是对象,无论对对象做了何种操作,都不会改变实参对象的...
  • c语言的形参和实参传递的区别

    千次阅读 多人点赞 2019-02-28 10:52:49
    参数传递,是在程序运行过程中,实际参数就会将参数值传递给相应形式参数,然后在函数中实现对数据处理返回过程。参数传递有3种方式: 值传递 地址传递 引用传递 tips: 被调用函数的形参只有函数被调用时...
  • 2.形参的类型决定了形参和实参交互的方式。 (引用->绑定,非引用->拷贝) 3.实参分为:被引用传递(引用形参是实参的别名),被值传递实参形参是两个相互独立的对象)。 4.传值参数:函数对形参做的所有...
  • 2、不同形式的实参和形参造成结果有何不同(会否对原数组或切片内容产生改变)? 情况设定及结论 原内容(数组/切片) 实参形式 形参形式 传递方式 在函数内对原内容操作结果 说明 array := [[5]...
  • JavaScript形参和实参

    2016-03-30 20:21:00
    本节要说明的有两点,一个是参数的传递方式,一个是形参和实参的数目。 参数的传递方式 上节已经讲到,在JavaScript中,有两种传值方式,按值传递引用传递,函数参数的传递也可分为按值传递引用传递。【例4-4...
  • Java封装性就是把对象属性对属性操作结合成一个独立单位,并尽可能隐藏内部细节。 它包含两个含义: 1)把对象全部属性对属性操作结合在起,形成一个不可分割独立单位(即对象)。 Java是一种纯粹...
  • Python3 函数的形参和实参

    千次阅读 2019-03-04 22:53:35
    实参的对应关系与形参的对应关系是按位置来依次对应的 说明: 实际参数形式参数通过位置进行传递的匹配 实参个数必须与形参个数相同2、序列传参: 序列传参是只指函数调用过程中,用*将序列拆解后按照为序列...
  • 在形参和实参的传递过程中,牵涉到大的类类型对象、容器类型对象或者不支持拷贝操作的对象时,不适合采用值传递,应使用引用传递的方式。另外,实参形参传递的过程中,系统会忽略形参的顶层引用(可用变量赋值给常量...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,042
精华内容 416
关键字:

实参和形参的传递方式