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

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\n", a, b);swap(int, a, b)printf("After swap.  a: %d, b: %d\n", a, b);return 0;
}

预处理之后的代码就是:

int main()
{int a = 23, b = 47;printf("Before swap. a: %d, b: %d\n", a, b);{ int t = a ; a = b ; b = t ; }printf("After swap.  a: %d, b: %d\n", 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 memberpublic MyInteger(int xIn) { x = xIn; } // constructorpublic int getValue() { return x; }  // retrieve valuepublic void insertValue(int xIn) { x = xIn;} // insert
}public class Swapping {// swap: pass references to objectsstatic void swap(MyInteger rWrap, MyInteger sWrap) {// interchange values inside objectsint 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

作者:阿凡卢
出处:http://www.cnblogs.com/luxiaoxun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
http://www.cnblogs.com/luxiaoxun/p/3999583.html

Swap in C C++ C# Java相关推荐

  1. java swap函数的包_java中swap函数

    ? ? ? 第1章 第2章 第3章 第4章 java语言概述 Java语言基础 对象与类 ...("swap方法里,a的值是" + a + ";b的值 是" + ...

  2. JAVA面试解析(有赞二面)

    作者:孤独烟 来自:打杂的ZRJ 本文的题目出自博客 http://www.54tianzhisheng.cn/2018/07/12/youzan/ 但是作者没有给出答案,博主斗胆来制作答案版. 也是 ...

  3. Java并发——CAS

    什么是CAS? CAS是Compare And Swap的简称.在Java中有很多实现,比如compareAndSwapObject()方法,或者compareAndSwapInt()方法等.多用在包 ...

  4. (重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...

    1.0建立二叉树的代码,在java中必须创建二叉树的方法必须用返回值,因为不存在c语言中的引用传递,在java中只有值传递 代码1为正确,代码2(没有使用返回值)为错误.那么为什么之前的例子中将对象作 ...

  5. java中形参不可以是对象吗_(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...

    1.0建立二叉树的代码,在java中必须创建二叉树的方法必须用返回值,因为不存在c语言中的引用传递,在java中只有值传递 代码1为正确,代码2(没有使用返回值)为错误.那么为什么之前的例子中将对象作 ...

  6. Java判断工作日计算,计算随意2个日期内的工作日

    当前位置:我的异常网» Java Web开发 » 计算随意2个日期内的工作日 计算随意2个日期内的工作日 www.myexceptions.net  网友分享于:2013-08-17  浏览:51次 ...

  7. 冷静对待你遇到的所有Java内存异常

    被人说烂的Java内存模型 Java内存模型的相关资料在网上实在是太多了,不管是过时的还是不过时的,网络上充斥的学习资料,比如各类研究Java内存模型的博文,也随着Java的发展,渐渐失去了其内容的准 ...

  8. java swarm_科学网—Java_Swarm编程:遇到麻烦了...... - 高德华的博文

    打开Eclipse,运行Simorg程序,出现如下错误信息: Execution protection violation # # An unexpected error has been detec ...

  9. java中各种时间格式的转化

    http://www.chinaitpower.com/A/2005-01-14/104881.html 使用java.util.Calendar返回间隔天数         static int g ...

最新文章

  1. 构建高可用LVS + keepalived+httpd和双主模型的keepalived方案
  2. Spring Boot配置文件加载顺序
  3. OpenResty请求参数处理
  4. Cocos2d-3.x版的HelloWorld工程分析 (二)
  5. ICPC 徐州 H Yuuki and a problem (树状数组套主席树)
  6. perf +火焰图使用
  7. 思科和华为/H3C命令对比表
  8. Java进阶知识点:协变与逆变
  9. C# 实体类序列化与反序列化一 (XmlSerializer)
  10. ABAP中分页控件的定义
  11. 电解电容串联的均压电阻计算
  12. Android多开/分身检测
  13. ios应用不通过应用商店下载
  14. Scikit-learn API:train_test_split函数 将数据分割为训练集和测试集
  15. 100天成就卓越领导力:新晋领导者的First100训练法
  16. 儿童定位手表app定制开发有哪些功能
  17. 2月编程语言排行榜谁还没有看?
  18. HDU1000题纪念
  19. 恭主驾到:新手都知道的审车流程,你都知道吗?
  20. 一小时刷完英语口语常用3000词汇(绿色护眼版)day9-词汇801-900

热门文章

  1. [置顶]常用存储过程集锦
  2. 视频过大怎么压缩变小
  3. vue2+vuex+vue-router 快速入门(三) vue 实例介绍
  4. 三十天学不会TCP,UDP/IP网络编程-IP头格式祥述
  5. 我的WCF之旅(10):如何在WCF进行Exception Handling
  6. 再谈CentOS 7程序自启动
  7. 运输层--TCP协议(2)
  8. Linux常用命令--uname
  9. 存储分析:RAID技术走向何方?
  10. 条款23: 必须返回一个对象时不要试图返回一个引用