由swap引发的关于按值传递和引用传递的思考与总结

  函数的参数传递定义:在调用一个函数时,将实参传递给形参。

  C++中函数的参数传递有按值传递、地址传递和引用传递3种方式。注意:地址也是一种值,按值传递和按地址传递都是单向的值传递方式,即形参都不会回传给实参。但是由于地址的特殊性,地址传递可以间接地改变实参的值,所以分开讨论。

一、按值传递

函数本身不对实参进行操作。

 1   #include<iostream>
 2   using namespace std;
 3   void swap(int,int);//函数声明
 4
 5  void main()
 6
 7   {
 8
 9     int a=2,b=3;
10
11    swap(a,b);//调用时,形参x、y重新申请了空间,把a、b值拷贝到形参,不对实参产生影响
12
13   cout<<"a = "<<a<<",b = "<<b<<endl;
14
15  }
16
17  void swap(int x,int y)//函数定义
18
19  {
20
21     int temp = x;
22
23     x = y;
24
25     y = temp;
26
27   }
28
29 执行结果如下:
30 a = 2,b = 3

二、地址传递

所谓地址传递,是指在函数定义时将形参生命成指针,这样调用函数时就需要指定地址形式的实参。

 1   #include<iostream>
 2   using namespace std;
 3   void swap(int *,int *);//函数声明
 4
 5  void main()
 6
 7   {
 8
 9     int a=2,b=3;
10
11    swap(&a,&b);//swap中不是交换了x和y的值,而是交换了两个指针指向的两个地址处的值;因为同一地址的数据值是相同的,从而间接地达到了回传参数的目的
12
13   cout<<"a = "<<a<<",b = "<<b<<endl;
14
15  }
16
17  void swap(int *x,int *y)//函数定义
18
19  {
20
21     int temp = *x;//"*"符号表示取指针指向的值
22
23     *x = *y;
24
25     *y = temp;
26
27   }
28
29 执行结果如下:
30     a = 3,b = 2

三、引用传递

c++中变量名对应着内存的存储位置,可以使用一个特定的内存地址访问到它,引用则引入了变量的另一个名字(别名),它和这个变量有同一内存地址,对应用的操作,也就是对被它引用的变量的操作。

 1   #include<iostream>
 2   using namespace std;
 3   void swap(int &,int &);//函数声明
 4
 5  void main()
 6
 7   {
 8
 9     int a=2,b=3;
10
11    swap(&a,&b);//将实参的地址放入C++为形参分配的内存空间中
12
13   cout<<"a = "<<a<<",b = "<<b<<endl;
14
15  }
16
17  void swap(int &x,int &y)//函数定义
18
19  {
20
21     int temp = x;//引用使用的时候,直接当变量名用
22
23     x = y;
24
25     y = temp;
26
27   }
28
29 执行结果如下:
30     a = 3,b = 2

  Java中,swap函数什么时候使用,由于何种必要使用?

在类中,实现两个成员变量值交换的swap方法:

 1 class Test
 2
 3 {
 4
 5   private int a;
 6
 7   private int b;
 8
 9
10
11   //swap函数没有使用形参的必要性,本身就可以直接操作内成员a,b,不存在参数拷贝,a,b值交换成功
12
13   public void swap()
14
15   {
16
17     int temp = this.a;
18
19     this.a = b;
20
21     this.b = temp;
22
23   }  
24
25 }

交互一个数组中的两个元素的值

public static void main(String []args)
{
    int a[] = {1,2};
    int temp = a[0];
    a[0] = a[1];
    a[1] = temp;
    System.out.println("a[0] = " + a[0] + ",a[1] = " + a[1]);
}
打印结果:
a[0] = 2,a[1] = 1

两个数组交换值

    public static void main(String args[])
    {
          int a[] = {1,2};
          int b[] = {3,4};
          int temp[] = a;
          a = b;
          b = temp;
        for(int i=0;i<a.length;i++)
        {
          System.out.print("a[" + i + "]=" + a[i] + " ");
        }
        System.out.println();
      for(int j=0;j<b.length;j++)
      {
          System.out.print("b[" + j + "]=" +b[j] + " ");
      }
    }
打印结果:
a[0]=3 a[1]=4
b[0]=1 b[1]=2

对于引用数据类型

public class ReferValue
{
    static String ss = "hello";

    public static void change(String str)
    {
        str = "world";//调用change函数时,传ReferValue.ss,不能改变成员ss值。
    // ss = "ss changed";//直接反问修改,可以改变ss值

   }   public static void main(String args[])  {    change(ReferValue.ss);//将类或者对象的成员变量,“暴露出来”,当成实参传递给形参,这种做法就有待商榷。
  }}

  附Java官方文档对于函数参数传递的解释(出自:http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html):

Passing Information to a Method or a Constructor

Passing Primitive Data Type Arguments

Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost. Here is an example:

public class PassPrimitiveByValue {

    public static void main(String[] args) {

        int x = 3;

        // invoke passMethod() with
        // x as argument
        passMethod(x);

        // print x to see if its
        // value has changed
        System.out.println("After invoking passMethod, x = " + x);

    }

    // change parameter in passMethod()
    public static void passMethod(int p) {
        p = 10;
    }
}

When you run this program, the output is:

After invoking passMethod, x = 3

Passing Reference Data Type Arguments

Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before.However, the values of the object‘s fields can be changed in the method, if they have the proper access level.

For example, consider a method in an arbitrary class that moves Circle objects:

public void moveCircle(Circle circle, int deltaX, int deltaY) {
    // code to move origin of circle to x+deltaX, y+deltaY
    circle.setX(circle.getX() + deltaX);
    circle.setY(circle.getY() + deltaY);

    // code to assign a new reference to circle
    circle = new Circle(0, 0);
}

Let the method be invoked with these arguments:

moveCircle(myCircle, 23, 56)

  Inside the method, circle initially refers to myCircle.

  The method changes the x and y coordinates of the object that circle references (i.e., myCircle) by 23 and 56, respectively. These changes will persist when the method returns.

  Then circle is assigned a reference to a new Circle object with x = y = 0. This reassignment has no permanence, however, because the reference was passed in by value and cannot change. Within the method, the object pointed to by circle has changed, but, when the method returns, myCircle still references the same Circle object as before the method was called.

时间: 2024-08-01 12:47:39

由swap引发的关于按值传递和引用传递的思考与总结的相关文章

python对象的复制问题,按值传递?引用传递?

这部分这篇博文说的很明白,转了过来 作者:winterTTr (转载请注明)http://blog.csdn.net/winterttr/article/details/2590741#0-tsina-1-71597-397232819ff9a47a7b7e80a40613cfe1 我想,这个标题或许是很多初学者的问题.尤其是像我这样的对C/C++比较熟悉,刚刚进入python殿堂的朋友们 .C/C++的函数参数的传递方式根深蒂固的影响这我们的思维--引用?传值?究竟是那种呢. 呵呵,语言的特性

项目中遇到的引用传递引发的问题

最近项目部署在服务器以上出现了一个问题,就是下拉框出现了本来不应该存在在这个下拉框中的分类,领导让我和另一个实习生一起找原因在哪,下拉框中的内容是程序起来的时候加载到缓存中的,代码是这样 码表会被放到一个HashMap里,大致就是map<1001,<1,"竞赛">>  这个意思.当时我全部思维都在考虑是不是加载过程中出现了问题,甚至想到了是不是因为线程不安全,在插入当前键的时候,脏读了.但是觉得又不太可能,当前key里面多的仅仅是另一个key全部的数据,不会这么

Java中的值传递和引用传递

解释 1.Java中有没有引用传递? 答:Java中只有按值传递,没有按引用传递! 2.当一个对象被当作参数传递到一个方法中后,在此方法中可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递. Java参数,不管是原始类型还是引用类型,传递的都是副本(有另外一种说法是传值,但是说传副本更好理解吧,传值通常是相对传址而言).如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的,如果在函数中改变了副本

Java中String是不是引用传递?

本文转自:http://www.jcodecraeer.com/a/chengxusheji/java/2012/0805/340.html 编者语:书上都说string是引用类型,但事实上我所看到的string和所谓的值类型没有什么区别,但通过看以下的文章,明白了: 1.string a="abc";之后,如果a="xy",则是a并没有改变内存中已经存在的"abc",而是又创建了另外一个实例.实际上相当于:string a=new String

C++ Primer 学习笔记_17_从C到C++(3)--引用、const引用、引用传递、引用作为函数返回值、引用与指针区别

欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 一.引用 1.引用是给一个变量起别名 变量: 名称 空间 引用: 引用不是变量 引用仅仅是变量的别名 引用没有自己独立的空间 引用要与它所引用的变量共享空间 对引用所做的改变实际上是对它所引用的变量的改变 引用在定义的时候必须要进行初始化 引用一经初始化,不能重新指向其他变量 2.定义引用的一般格式: (1)类型  &引用名 = 变量名: (2)例如: int a=1; int &b=a; // b是a的别名,因此a和b是同一个单元 (3)

值传递和引用传递-----函数参数传递的两种方式

回顾: 在定义函数时函数括号中的变量名成为形式参数,简称形参或虚拟参数:在主调函数中调用一个函数时,该函数括号中的参数名称为实际参数,简称实参,实参可以是常量.变量或表达式. 注意: 1.C语言中实参和形参之间的额数据传递是单向的“值传递”,单向传递,只能由实参传给形参,反之不能. 2.被调用函数的形参只有函数被调用时才会临时分配存储单元,一旦调用结束占用的内存便会被释放. 3.”按值传递“中包括值传递(实实在在的值啊!)和指针传递(指针传递参数本质上是值传递的方式,它所传递的是一个地址值),传

C#中值传递与引用传递的区别

以值传递参数 当实参当作值来传递时,就产生了一个新的拷贝. class Test     { static void Main(string[] args)         { int x=8; Fo(x); Console.WriteLine("x={0}", x); } static void Fo(int p) { p = p + 1; Console.WriteLine("p={0}", p); } }    程序运行结果为:p=9,x=8;即X的值不会受P

c/c++值传递和引用传递

今天看数据结构的时候,因为是c语言版的,刚开始学的时候就对指针搞的焦头烂额,今天,发现参数传递的时候,&符号也莫名其妙,搜了一篇好文,转载下来. 一. 函数参数传递机制的基本理论 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传递.以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数. 值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存

JAVA随笔篇二(深入分析JAVA简单类型、String和对象的值传递和引用传递)

关于JAVA的值传递和引用传递,翻看了很多资料和博客,感觉大多数讲的很乱,都是自己明白了之后就不讲了的样子,终于算是比较理解这几个概念了,下面做一个总结. 1.简单类型的参数传递 Java方法的参数是简单类型的时候,是按值传递的 (pass by value).下面举一个经典的swap函数: 无法交换值的方法: package TestTransferPack; public class TestTransfer { public static void main(String[] args)