一.java形参传递方式(传值)
背景介绍:1.java常量(声明常量必须用final关键字)一般位于常量池,为方法区的一部分,被所有线程所共享
2.java变量一般位于虚拟机栈,为每个线程私有
3.java对象一般位于堆,被所有线程所共享
附:
int a = 3; int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。
1,String str1 = "hello";2,String str2 = new String("hello");
第一种方法:引用str1被存放在栈区,字符串常量"hello"被存放在常量池,引用str1指向了常量池中的"hello"(str1中的存放了常量池中"hello"的地址)。
第二种方法:引用str2被存放在栈区,同时在堆区开辟一块内存用于存放一个新的String类型对象。(同上,str2指向了堆区新开辟的String类型的对象)
示例介绍:
1.
public static void main(String[] args) {
int x=3;
changeInt(x);
System.out.println("After change, x = " + x);
}
public static void changeInt(int i) {
i=2;
}
分析:1.x指向内容为3的地址空间 (栈中)
2 i复制内容为3的地址空间的内容
3.i的值发生了改变,但此时x所属地址空间的内容并未发生改变
2.
public static void main(String[] args) {
StringBuffer x = new StringBuffer("Hello ");
changeData(x);
System.out.println("After change, x = " + x);
}
public static void changeData(StringBuffer strBuf) {
strBuf = new StringBuffer("Hi ");
//strBuf.append("world"); strBuf也指向了x指向的内存空间,而不是指向x的一个拷贝,所有此时x的值会发生变化
}
分析:1.x指向内容为Hello的地址空间 (堆)
2 strBuf指向内容为Hello的地址空间
3.strBuf指向新开辟的地址空间,此时原来的指向失效,即x所属地址空间内容并未发生改变
综上所述:感觉java到处都被封装成指针,因为指针是指向某一内存地址的变量,在示例1中,在使用上int具有指针的特性,但由于无法实现地址传递/引用传递,导致最终x仍未变化,在示例2中,strBuf.append("world")类似于c++的引用传递;
二、c/c++形参传递方式(传值、传地址、传引用)
背景介绍:
示例1:传值/传地址
传值方式:
#include<stdio.h>
void fun(int a, int b) // 此处a, b为形参
{
a++;
b++;
}
void main()
{
int a=1, b=2;
fun(a, b); // 按传值方式调用函数fun,此处a,b为实参
printf("%d, %d\n", a, b); // 输出a=1, b=2
}
传地址方式:
#include<stdio.h>
void fun(int *a, int *b)
{
*a = 4; *b = 5;
}
void main()
{
int a=1, b=2; fun(&a, &b); // 按传地址方式调用函数fun
printf("%d, %d\n", a, b); // 输出a=4, b=5
}
示例2:传引用
#include <iostream>
using namespace std;
void swap(int&,int&);
int main()
{
int a = 3, b = 4;
cout << "a = " << a << ", b = "
<< b << endl;
swap(a,b);
cout << "a = " << a << ", b = "
<< b << endl;
system("pause");
return 0;
}
void swap(int &x,int &y)
{
int t = x;
x = y;
y = t;
}