Call by value : 값에 의한 호출
함수가 호출될 때, 메모리 공간 안에서는 함수를 위한 별도의 임시공간이 생성되고, 종료 시 해당 공간은 사라진다.
함수 호출 시 전달되는 변수 값을 복사해서 함수 인자로 전달하고, 복사된 인자는 함수안에서 지역적으로 사용되기 때문에 local value 속성을 가진다.
=> 함수 안에서 인자 값이 변경되더라도, 외부 변수 값은 변경되지 않는다.
Call by reference : 참조에 의한 호출
함수 호출 시 인자로 전달되는 변수의 레퍼런스를 전달한다.
=> 함수 안에서 인자 값이 변경되면, argument로 전달된 객체의 값도 변경됨
자바의 경우 항상 call by value로 값을 넘긴다.
C/C++와 같이 변수의 주소값 자체를 가져올 방법이 없으며, 이를 넘길 수 있는 방법 또한 없다. reference type(참조 자료형)을 넘길 시에는 해당 객체의 주소값을 복사하여 이를 가지고 사용한다.
=> 따라서 원본 객체의 프로퍼티까지는 접근이 가능하나, 원본 객체 자체를 변경할 수는 없다.
User a = new User("Alice"); // 1
foo(a);
public void foo(User b){ // 2
b = new User("Bob"); // 3
}
/*
==========================================
// 1 : a에 User 객체 생성 및 할당(새로 생성된 객체의 주소값을 가지고 있음)
a -----> User Object [name = "Alice"]
==========================================
// 2 : b라는 파라미터에 a가 가진 주소값을 복사하여 가짐
a -----> User Object [name = "Alice"]
↑
b -----------
==========================================
// 3 : 새로운 객체를 생성하고 새로 생성된 주소값을 b가 가지며 a는 그대로 원본 객체를 가리킴
a -----> User Object [name = "Alice"]
b -----> User Object [name = "Bob"]
*/
파라미터에 객체/값의 주소값을 복사하여 넘겨주는 방식을 사용하고 있는 Java는 주소값을 넘겨 주소값에 저장되어 있는 값을 사용하는 call by reference라고 오해할 수 있다.
C/C++
int a = 10;
int b = a;
cout << &a << ", " << &b << endl; // out: 0x7ffeefbff49c, 0x7ffeefbff498
a = 11;
cout << &a << endl; // out: 0x7ffeefbff49c
C/C++에서는 생성한 변수마다 새로운 메모리 공간을 할당하고, 값을 덮어씌우는 형식으로 값을 할당한다.
Java
int a = 10;
int b = a;
System.out.println(System.identityHashCode(a)); // out: 1627674070
System.out.println(System.identityHashCode(b)); // out: 1627674070
a = 11;
System.out.println(System.identityHashCode(a)); // out: 1360875712
Java도 마찬가지로 생성한 변수마다 새로운 메모리 공간을 갖는다.
하지만 그 메모리 공간에 값 자체를 저장하는 것이 아니라, 값을 다른 메모리 공간에 할당하고 이 주소값을 저장한다.
즉, 변수는 주소값을 값으로 가지고 있다.
C/C++와 Java 비교
C/C++ | Java
|
a -> [ 10 ] | a -> [ XXXX ] [ 10 ] -> XXXX(위치)
b -> [ 10 ] | b -> [ XXXX ]
|
값 변경
a -> [ 11 ] | a -> [ YYYY ] [ 10 ] -> XXXX(위치)
b -> [ 10 ] | b -> [ XXXX ] [ 11 ] -> YYYY(위치)
b = a;일 때, a의 값을 b의 값으로 덮어 씌우는 것은 같지만,
실제 값을 저장하는 것과 값의 주소값을 저장하는 것의 차이가 존재한다.
C/C++에서는 주소값 자체를 인자로 넘겼을 때 값을 변경하면 새로운 값으로 덮어 쓰여 기존 값이 변경되고
Java에서는 주소값이 덮어 쓰여지므로 원본 값은 전혀 영향이 가지 않는다.
Call by value
데이터 값을 복사해서 함수로 전달 => 원본 데이터 변경 X
하지만 인자를 넘겨줄 때마다 메모리 공간을 할당 => 메모리 공간 더 차지함
Call by reference
메모리 공간 할당 문제는 해결
원본 값 변경 위험 존재
https://gyoogle.dev/blog/computer-language/Java/Call%20by%20value%20&%20Call%20by%20reference.html