본문 바로가기

컴쟁이의 알고리즘

[Java] Call by Value 와 Call by Reference

  Java 뿐만 아니라 C나 Python에서도 적용되는 이야기입니다.

 

  저는 컴퓨터공학과를 나왔는데 1학년 때 바로 배운 언어가 C언어였습니다.

그런데 제가 군대를 다녀오는 사이에 1학년 때 배우는 언어가 C++로 바뀌어있더랍니다.

살짝 세대 차이를 느꼈지요.

 

  각설하고 C에서 배우는 중요 개념 중 하나가 Call by Value와 Call by Reference입니다.

이게 과연 무엇일까요?

 

  이 두 개념은 함수에 parameter를 넘길 때 어떻게 넘어가는지 형태를 나타내는 개념입니다.

Call by Value는 그 값이 복사되어 넘어간다는 것이고,

Call by Reference는 C로 따지면 해당 배열 등을 가리키고 있는 포인터의 주소값이 넘어가는 것입니다.

 

  그래서 Call by Value로 넘어가는 변수들은 함수 내에서 변동이 있더라도 함수가 끝나 다시 원래 위치로 돌아오게되면

넘기기 이전 값이 그대로 유지되어 있지만,

Call by Reference로 넘어가는 변수들은 해당 변수를 가리키는 포인터가 넘어갔기 때문에 함수 내부에서

해당 변수를 바꾸면 밖에서와 같이 포인터를 타고 해당 변수의 원본으로 바로 넘어가기 때문에

원본 또한 바뀌게 되는 것입니다.

 

  이렇게 Call by Value와 Call by Reference를 C에서 배우고 나서 다른 언어로 넘어가는데,

문제는 다른 언어에는 '포인터'의 개념이 없는 경우가 많다는 것입니다.

그래서 넘겨줄 포인터도 없는데 Call by Reference가 되는걸까? 라는 혼동이 오기 시작하면

그때에 한번 짚고 넘어가야 나중에 편할 것 같습니다.

 

  오늘 이런 이야기를 하는 이유는 저도 오늘 알고리즘 문제를 풀던 중에 2차원 배열을 parameter로 넘기는 과정에서

실수를 했기 때문입니다.

문제를 쭉 풀고 있는데 결과가 이상하게 나오길래 과정을 출력해보았더니 이전에 변동시킨 값이

그대로 유지된 상태에서 다음 단계로 넘어가버린 것이 원인이었습니다.

그런데 지금까지는 한번도 Java에서 이런 문제에 대해 생각해본적이 없기 때문에 떠올리는데 시간이 조금 걸렸습니다.

이것 참 부끄럽네요. 하하...

 

  결국 2차원 배열을 복사하는 함수를 하나 만들어 2차원 배열을 넘겨줘야할 때마다 복사해서 넘겨주니 문제가 풀렸습니다. 그런데 문득 포인터도 없는 Java에서 이런 구현이 어떻게 되어있는지 궁금해졌습니다.

 

  그래서 구글을 탐색해본 결과 Java에서는 포인터와 비슷한 역할을 하는 '주소값'이 전달된다고 합니다.

이때가 되서야 Java를 처음 배울적에 System.out.println(배열의 이름)으로 찍어본 배열의 주소값이 떠올랐습니다.

비록 이런 주소값을 포인터처럼 연산을 통해 직접 접근하는 등의 동작은 할 수 없지만 Call by Reference가 가능하게 만든 편의성에 대해 감탄하는 하루였습니다.

참고로 primitive type을 제외한 모든 객체 등은 이와 같은 Call by Reference로 넘겨진다고 합니다.

 

  여러분도 혹시 뭔가 값이 이상하게 넘어간다 싶을 때에는 한번쯤 확인해보시는 건 어떨까요?

 

  읽어주셔서 감사합니다.

  좋은 하루 되세요. :)