call by value : 값을 복사한다.

코딩/Java 2019. 9. 16. 00:29

 call by value, 즉 값 복사 호출 방식은 반드시 알고 넘어가셔야 하는 개념 중 하나입니다. 이것은 간단하게 말해서, 함수에 값이 전달이 될 때, 값이 copy 되어서 전달이 된다는 겁니다. 즉, 사본이 전달이 되는 셈입니다.

 

 


 다음 프로그램을 보면서 간단하게 이해를 해 보도록 하겠습니다.

 

 라인 바이 라인으로 끊어서 이해를 해 보도록 하겠습니다. 먼저, 5번째 줄과 6번째 줄에 a가 선언이 되고, b가 선언됩니다. 이 때, a에는 5가, b에는 3이 들어갑니다.

 

 

 그러면 이 상황입니다. 그 다음에 swap 함수가 호출이 되는데요. 이 때, a와 b의 값을 넘겨줍니다.

 

 

 이 때, 메모리 상황을 그려보면 위와 같습니다. 다음에, 12번째 줄에 t가 선언이 되었는데요. swap 내에서 선언이 되었기 때문에, 이 함수가 종료되면, 메모리에서 사라지게 됩니다.

 

 

 

 12번째 줄까지 수행이 된 후 상황입니다. 다음에 b의 값을 a에 넣고, t의 값을 b에 넣으면, main에서 부른 메서드 내에서는 3과 5가 서로 바뀌게 될 겁니다.

 

 

 그 다음에, 16번째 줄에 도달하면, swap 함수가 끝나게 됩니다. 이 때, main 함수에서 선언된 a와 b의 값이 변했나요? 안 그렇습니다. 왜냐하면, swap 메서드 내에서의 매개변수 a, b와, main 내의 a, b가 서로 다른 공간에 할당이 되어 있었기 때문입니다. 이렇게, 함수에 인자가 전달이 될 때, 값이 copy 되는 형식으로 (그러니까 사본이) 전달이 되는 것을 call by value 라고 이야기를 합니다.

 

 

 실행 결과는 예상대로 main에 있었던 a = 3, b = 5의 값은 바뀌지 않았습니다.

 

 


 그러면 이 경우에는 어떨까요? 객체가 넘겨지는 경우. 이 때도 똑같습니다.

 

 

 먼저 Point 클래스는 다음과 같습니다. 간단하게 x와 y를 필드로 선언해 놓은 것을 볼 수 있어요.

 

 

 main 함수와 foo 함수는 위와 같습니다. 먼저 13번째 줄에 (2,3)이다라는 포인트 정보를 넣고 있습니다. 그리고 14번째 줄에 foo라는 메서드를 호출하고 있어요. 14번째 줄을 수행하기 직전의 상황을 메모리에 그려보겠습니다.

 

 

 대략 이런 상황일 겁니다. 이 때, foo가 호출이 된 경우에, p를 인자로 넘겨줬어요. 이것이 값 복사가 됩니다.

 

 

 그러면, <0x23> 이라는 값이 매개변수로 받아질 거에요. 그러면, main의 p와, foo의 p가 같은 객체를 가리킨다는 것을 알 수 있는데요. 이를 우리는 얕은 복사라고 합니다. 이에 대한 설명은 관련글을 참고하시면 좋을 듯 싶어요.

 

 

[관련글]

얕은 복사와 깊은 복사는 무엇인가?

 

 

 이 때, p에 new Point(4,5), 그러니까 새로운 객체를 가리키는 값을 집어 넣습니다.

 

 

 그러면, 메모리 상황이 다음과 같이 될 겁니다. 그러면 이 때, main에 있는 p값에 영향이 갔나요? 가지 않았습니다. 단지 foo에 있었던 매개변수 p의 값이 변한 겁니다. <0x23>에서 <0x25>로. foo 함수가 끝나면, 지역 변수와 매개 변수는 소멸이 되는데요.

 

 

 이 때, <4,5>를 저장하고 있었던 객체는 유저 프로그램으로부터 접근할 수 있는 방법이 없습니다. 이를 가비지라고 부릅니다. 이를 detect 하는 방법은 여러가지가 있는데요. 프로그래밍 언어 시간에 배운 방법은, Root로부터 접근이 가능한 것을 marking을 합니다. 깊이 우선 탐색으로 하던지, 너비 우선 탐색으로 하던지요.

 

 

 그러면 Root로부터 도달 가능한 객체들이 있을 겁니다. 이러한 것들은 제거하지 않습니다. 그렇지 않은 것들은 메인이던 어디에서부터 도달 불가능한 객체다라고 판단하고 제거를 합니다. 그런 식으로 가비지를 처리해요.

 

 


 객체를 매개 변수로 넘겼을 때, 상황이 헷갈리실 수 있을 듯 싶습니다. 예제 하나 더 보겠습니다.

 

 

 foo 함수를 요렇게 바꾸었습니다. 그러면 메모리에 어떻게 그려지는지 다시 한 번 봅시다.

 

 

 그러면 매개변수 p와 main의 p가 같은 객체를 가리키는 상황에서 p.x에 7을 넣었습니다. 그러한 경우, <2,3>이 저장되어 있는 object에 접근을 하게 됩니다.

 

 

 그러면 foo가 끝났을 때, main의 p가 가리키고 있는 object의 값은 <2,3>에서 <7,3>으로 변경이 될 겁니다.