值传递和引用传递的区别
-
值传递是在方法函数入栈之后,将变量拷贝一份进入方法中。如果变量是基本类型,则直接进入方法函数的栈中;如果是引用类型变量,则与实参指向同一块堆区域。详情可见Java中的内存机制。
值传递可以传递基本类型数据和引用类型数据的地址。 -
引用传递是指在函数方法入栈后,将实际参数的地址直接传递到函数中。因此,在函数方法中对参数进行修改,将影响到实际参数的值。
引用传递传递的是句柄(也就是变量)本身的地址。
Java中只存在值传递(代码测试)
class Person {
public String name;
public Integer age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void change1(int x1,int x2){
int x3 = x1;
x1 = x2;
x2 = x3;
}
//这里交换的是方法change2中的person1和person2变量的指向
//实际上堆中存放的数据并没有改变,主函数中的person1和person2的指向也没有改变
public static void change2(Person person1,Person person2){
Person person3 = person1;
person1 = person2;
person2 = person3;
}
//由于传入的是person1,person2的地址
//change3可以对其指向的堆中的数据进行更改
//因此,引用类型变量的属性值发生变化
public static void change3(Person person1,Person person2){
int age = person1.age;
person1.age = person2.age;
person2.age = age;
}
public static void main(String[] args){
int a = 10;
int b = 20;
Person person1 = new Person();
Person person2 = new Person();
person1.age = 11;
person2.age = 12;
change1(a,b);
//result: a = 10,b = 20
System.out.println(a + " " + b);
change2(person1,person2);
//result: person1.age = 11,person2.age = 12
System.out.println("" + person1 + " " + person2);
change3(person1,person2);
//result: person1.age = 12,person2.age = 11
System.out.println("" + person1 + " " + person2);
}
}
C++中存在引用传递(代码测试)
struct Person {
std::string name;
int age;
std::string toString() const {
return "Person{name='" + name + "', age=" + std::to_string(age) + "}";
}
};
void change1(int& x1, int& x2) {
int x3 = x1;
x1 = x2;
x2 = x3;
}
void change2(Person*& person1, Person*& person2) {
Person* person3 = person1;
person1 = person2;
person2 = person3;
}
void change3(Person* person1, Person* person2) {
int age = person1->age;
person1->age = person2->age;
person2->age = age;
}
int main() {
int a = 10;
int b = 20;
Person* person1 = new Person();
Person* person2 = new Person();
person1->age = 11;
person2->age = 12;
change1(a, b);
// result: a = 20, b = 10
std::cout << a << " " << b << std::endl;
change2(person1, person2);
// result: person1->age = 12, person2->age = 11
std::cout << person1->toString() << " " << person2->toString() << std::endl;
change3(person1, person2);
// result: person1->age = 11, person2->age = 12 (再次交换)
std::cout << person1->toString() << " " << person2->toString() << std::endl;
delete person1;
delete person2;
return 0;
}