Java和C++中的参数传递
来源:互联网 发布:罗马2全面战争mac版 编辑:程序博客网 时间:2024/06/08 08:01
1概念定义
1.1按值传递:
将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。
1.2按引用传递:
将一个参数传递给一个函数时,函数接收的是原始值的内存地址,不是值的副本。因此,如果函数修改了该参数指向的内容,调用代码中的原始值也随之改变。
2 C++和Java应用程序中的参数传递
C++和Java中,当参数不是引用时,传递的都是该值的一个副本(按值传递)。
区别在于引用:
在C++中参数是引用时,您传递的就是这个引用,或者内存地址(按引用传递)。
在Java中参数是对象引用时,您传递的是该引用的一个副本(按值传递),而不是引用本身,但是调用方法的对象引用和副本都指向同一个对象。
总之,Java应用程序在传递不同类型的参数时,其作法与C++并无不同。Java应用程序按值传递所有参数,这样就制作所有参数的副本,而不管它们的类型。
3 实例解析
#include
using namespace std;
void modify(int a, int *p, int &r)
{
printf("in modify.../n");
a = 0;
*p = 7;
p = 0;
r = 0;
printf("a is %d/n", a);
printf("p is %d/n", p);
printf("r is %d/n", r);
}
int main ()
{
int val, ref;
int *pint;
val = 10;
ref = 50;
pint = (int*)malloc(sizeof(int));
*pint = 15;
printf("val is %d/n", val);
printf("pint is %d/n", pint);
printf("*pint is %d/n", *pint);
printf("ref is %d/n/n", ref);
printf("calling modify/n");
modify(val, pint, ref);
printf("returned from modify/n/n");
printf("val is %d/n", val);
printf("pint is %d/n", pint);
printf("*pint is %d/n", *pint);
printf("ref is %d/n", ref);
return 0;
}
程序运行结果:
val is 10
pint is 4262128
*pint is 15
ref is 50
calling modify
in modify...
a is 0
p is 0
r is 0
returned from modify
val is 10
pint is 4262128
*pint is 7
ref is 0
这段代码声明了三个变量:两个整型变量和一个指针变量。将所有三个变量作为参数传递给modify()。前两个参数是按值传递的,最后一个参数是按引用传递的。
Modify()的函数原型表明最后一个参数要作为引用传递。C++按值传递所有参数,引用除外;
Modify()更改了所有三个参数的值:
将第一个参数设置为0。
将第二个参数所指向的值设置为7,然后将第二个参数设置为0。
将第三个参数设置为0。
将第一个参数设置为0。
将第二个参数所指向的值设置为7,然后将第二个参数设置为0。
将第三个参数设置为0。
将新值打印出来,然后函数返回。
当执行返回到main时,再次打印出这三个参数的值以及指针所指向的值。
第一个和第二个参数由于按值传递,所以实参不受modify函数的影响。但指针所指向的值改变了。最后一个参数由于按引用传递,所以实参被modify函数改变了。
class Test
{
publicstaticvoid modify(int a, StringBuffer r1, StringBuffer r2)
{
System.out.println("in modify...");
a = 0;
r1 = null; //1
r2.append(" taste good");
System.out.println("a is " + a);
System.out.println("r1 is " + r1);
System.out.println("r2 is " + r2);
}
publicstaticvoid main(String args[])
{
int val;
StringBuffer sb1, sb2;
val = 10;
sb1 = new StringBuffer("apples");
sb2 = new StringBuffer("pears");
System.out.println("val is " + val);
System.out.println("sb1 is " + sb1);
System.out.println("sb2 is " + sb2);
System.out.println();
System.out.println("calling modify");
//按值传递所有参数
modify(val, sb1, sb2);
System.out.println("returned from modify");
System.out.println("");
System.out.println("val is " + val);
System.out.println("sb1 is " + sb1);
System.out.println("sb2 is " + sb2);
}
}
运行结果:
val is 10
sb1 is apples
sb2 is pears
calling modify
in modify...
a is 0
r1 is null
r2 is pears taste good
returned from modify
val is 10
sb1 is apples
sb2 is pears taste good
代码声明了三个变量:一个整型变量和两个对象引用。将所有三个变量作为参数传递给modify()。
Modify()更改了所有三个参数的值:
将第一个参数(整数)设置为0。
将第一个对象引用r1设置为null。
保留第二个引用r2的值,但调用append()更改它所引用的对象
返回到main()时,整型的val没有改变。对象引用sb1也没有改变。
如果sb1是按引用传递的,正如许多人声称的那样,它将为null。但是,因为Java中按值传递所有参数,所以是将sb1的引用的一个副本传递给了modify()方法。
当modify()中将r1设置为null时,它只是对sb1的引用的一个副本进行了该操作,而不是像C++中那样对原始值进行操作。
第二个对象引用sb2打印出的是在modify()中设置的新字符串。是因为modify()中的引用副本和sb2指向同一个对象,所以对复制的引用所调用的方法更改的是同一个对象。
3.3经典的交换函数
3.3.1利用指针来实现
void swap(int *a, int *b)
{
int temp = *b;
*b = *a;
*a = temp;
}
int main (int argc, char** argv)
{
int val1, val2;
val1 = 10;
val2 = 50;
swap(&val1, &val2);
return 0;
}
3.3.2利用引用来实现
void swap(int &a, int &b)
{
int temp = b;
b = a;
a = temp;
}
int main (int argc, char** argv)
{
int val1, val2;
val1 = 10;
val2 = 50;
swap(val1, val2);
return 0;
}
3.3.3 Java利用引用来实现
class Swap
{
publicstaticvoid swap(Integer a, Integer b)
{
Integer temp = a;
a = b;
b = temp;
}
publicstaticvoid main(String args[])
{
Integer a, b;
a = new Integer(10);
b = new Integer(50);
System.out.println("before swap...");
System.out.println("a is " + a);
System.out.println("b is " + b);
swap(a, b);
System.out.println("after swap...");
System.out.println("a is " + a);
System.out.println("b is " + b);
}
}
运行结果:
before swap...
a is 10
b is 50
after swap...
a is 10
b is 50
Java中的函数参数传值是按值传值!
3.4 Java版本的综合实例
class MyInteger
{
privateint inner;
public MyInteger(int inner)
{
this.inner = inner;
}
publicvoid setInt(int i)
{
inner = i;
}
publicint getInt()
{
returninner;
}
public String toString()
{
return"" + inner;
}
}
class Swap
{
publicstaticvoid swap(MyInteger a, MyInteger b)
{
pl("swap");
MyInteger temp = a;
a = b;
b = temp;
}
publicstaticvoid swapI(MyInteger a, MyInteger b)
{
pl("swapI");
MyInteger temp = a;
a = new MyInteger(b.getInt());
b = new MyInteger(temp.getInt());
}
publicstaticvoid swapII(MyInteger a, MyInteger b)
{
pl("swapII");
int temp = a.getInt();
a.setInt(b.getInt());
b.setInt(temp);
}
publicstaticvoid main(String[] args)
{
MyInteger a = new MyInteger(1);
MyInteger b = new MyInteger(2);
pl(a);
pl(b);
swap(a, b);
pl(a);
pl(b);
swapI(a, b);
pl(a);
pl(b);
swapII(a, b);
pl(a);
pl(b);
}
privatestaticvoid pl(Object a)
{
System.out.println(a);
}
}
运行结果:
1
2
Swap //交换的是实参的引用副本,所以对原来的调用函数没什么影响
1
2
swapI //操作的是实参的引用副本
1
2
swapII //操作的是引用副本所指向的内容,所以对调用函数会发生变化
2
1
总之,在函数参数传递的过程当中Java自动调用Object::clone(),想要进行深拷贝的调用,自己要显示的指明!
publicstaticvoid swap(MyInteger i, MyInteger j)
{
i.setValue(40);
j.setValue(50);
}
swap((MyInteger)a.clone(),(MyInteger)b.clone());
3.5 思考下面的例子
package hziee;
publicclass StringTest
{
staticvoid func(String s)
{
s += "tail";
}
staticvoid test()
{
String a = "abc";
func(a);
System.out.println(a);
}
publicstaticvoid main(String[] args)
{
test();
}
}
看了上面的介绍内容应该明白是什么原因了吧?
- c和c++中的函数参数传递
- Java中的值传递和引用传递(参数传递)
- C#中的参数传递
- C#中的参数传递
- C#中的参数传递
- C#中的参数传递
- Java中的变量赋值和参数传递
- Java和C++中的参数传递
- Java中的参数传递问题和图解
- NDK java和c参数传递
- java中的参数传递
- java中的参数传递
- Java中的参数传递
- java中的参数传递
- Java中的参数传递
- java中的参数传递
- java中的参数传递
- JAVA中的参数传递
- java的运行机制详解
- 用户层下拦截系统api的原理与实现
- 深入剖析MMORPG游戏服务器端的设计
- Java是传值还是传引用
- 【转帖】Servlet技术
- Java和C++中的参数传递
- 深入研究 String
- 未来的创业
- 蓝屏"的硬件原因及解决
- Oracle两个基本概念帮你了解体系结构
- 深入Linux PAM体系结构
- JSP中文验证码及源代码实现
- 10个最大的互联网营销Web 2.0的论坛和博客资源
- MYSQL和ORACLE的一些操作区别