zoukankan      html  css  js  c++  java
  • Swap in C C++ C# Java

    写一个函数交换两个变量的值。

    C:

    错误的实现:

    void swap(int i, int j) 
    {
       int t = i;
       i = j;
       j = t;
    }

    因为C语言的函数参数是以值来传递的(pass by value),参数传递时被copy了,所以函数中交换的是复制后的值。

    正确的实现:

    指针版:

    void swap(int *i, int *j) 
    {
       int t = *i;
       *i = *j;
       *j = t;
    }

    函数使用时候传递的是变量的地址,如 swap(&a,&b),函数交换的是两个指针指向的值,就是两个变量的值,所以交换成功。

    预处理版:

    #define swap(type, i, j) {type t = i; i = j; j = t;}

    预处理的实质是文本替换(textual substitution)。

    如下代码:

    #define swap(type, i, j) {type t = i; i = j; j = t;}
    
    int main() 
    {
        int a = 23, b = 47;
        printf("Before swap. a: %d, b: %d
    ", a, b);
        swap(int, a, b)
        printf("After swap.  a: %d, b: %d
    ", a, b);
        return 0;
    }

    预处理之后的代码就是:

    int main() 
    {
        int a = 23, b = 47;
        printf("Before swap. a: %d, b: %d
    ", a, b);
         { int t = a ; a = b ; b = t ; }
        printf("After swap.  a: %d, b: %d
    ", a, b);
        return 0;
    }

    所以可以正确的交换两个变量的值。

    C++:

    方式一:如同C语言使用指针。
    方式二:使用“引用”(&)

    void swap(int& i, int& j) 
    {
        int t = i;
        i = j;
        j = t;
    }

    C++的函数参数使用引用(&),值通过引用传递(pass by reference),函数中的参数不被 copy(如果传的是类就不会调用拷贝构造函数),所以在函数中能正确交换两个变量的值。

    C#:

    static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp;
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }

    不要忘了ref关键字,如果没有是不能正确交换的!

    Java:

    java.util.Collections;
    public static void swap(List<?> list,int i,int j)

    使用集合中的static方法。

    如果不使用数组集合,Java中没有一个简单的函数来交换两个变量的值。除非自己封装一下:

    // MyInteger: similar to Integer, but can change value
    class MyInteger {
       private int x;                   // single data member
       public MyInteger(int xIn) { x = xIn; } // constructor
       public int getValue() { return x; }  // retrieve value
       public void insertValue(int xIn) { x = xIn;} // insert
    }
    
    public class Swapping {
       // swap: pass references to objects
       static void swap(MyInteger rWrap, MyInteger sWrap) {
          // interchange values inside objects
          int t = rWrap.getValue();
          rWrap.insertValue(sWrap.getValue());
          sWrap.insertValue(t);
       }
    
       public static void main(String[] args) {
          int a = 23, b = 47;
          System.out.println("Before. a:" + a + ", b: " + b);
          MyInteger aWrap = new MyInteger(a);
          MyInteger bWrap = new MyInteger(b);
          swap(aWrap, bWrap);
          a = aWrap.getValue();
          b = bWrap.getValue();
          System.out.println("After.  a:" + a + ", b: " + b);
       }
    }

    C#这点和Java是一样的,C#版的交换如果不使用ref关键字,swap函数也没法正确工作。

    虽然C#、java通过函数参数可以修改参数的值,但是这点和C++的引用有很大的区别。

    看看如下函数:

    public void tricky(Point arg1, Point arg2)
    {
        arg1.x = 100;
        arg1.y = 100;
        Point temp = arg1;
        arg1 = arg2;
        arg2 = temp;
    }
     
    public static void main(String [] args)
    {
        Point pnt1 = new Point(0,0);
        Point pnt2 = new Point(0,0);
        System.out.println("X: " + pnt1.x + " Y: " +pnt1.y);
        System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
        System.out.println(" ");
        tricky(pnt1,pnt2);
        System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);
        System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
    }

    执行这个函数,将得到以下输出:

    ———————————————————-
    X: 0 Y: 0
    X: 0 Y: 0

    X: 100 Y: 100
    X: 0 Y: 0
    ———————————————————-

    当Java传递对象给函数之后,两个引用指向了同一对象:

    当被传递给函数之后,一个对象至少存在两个引用

    Java复制并传递了“引用”的值,而不是对象。因此,方法中对对象的计算是会起作用的,因为引用指向了原来的对象。但是因为方法中对象的引用是“副本”,所以对象交换就没起作用。如下图所示,交换动作只对方法中的引用副本起作用了,不影响方法外的引用。所以不好意思,方法被调用后,改变不了方法外的对象的引用。如果要对方法外的对象引用做交换,我们应该交换原始的引用,而不是它的副本。

    只有传入函数的引用交换了,原始引用则没有。

    参考: 

    http://www.cs.utsa.edu/~wagner/CS2213/swap/swap.html
    http://stackoverflow.com/questions/1363186/is-it-possible-to-write-swap-method-in-java
    http://www.importnew.com/3559.html

  • 相关阅读:
    WindowXP 下Android 开发环境搭建
    机房收费系统个人版——DataGridView控件怎么用?
    IOS开发(64)之GCD任务最多只执行一次
    第八学 linux内核——内存寻址——段机制(2)
    Git clone远程仓库
    vi中如何跳转到指定行数
    _STORAGE_WRITE_ERROR_:./Application/Runtime/Cache/Home/f8995a0e1afcdadc637612fae5a3b585.php
    git 报错:没有权限 remote: error: unable to unlink old 'README.md' (Permission denied)
    mytop安装,使用mytop监控MySQL性能 (总结)
    一起谈.NET技术,如何解决“呈现控件时出错”的问题 狼人:
  • 原文地址:https://www.cnblogs.com/luxiaoxun/p/3999583.html
Copyright © 2011-2022 走看看