call by value와 call by referece, call by address의 차이가 무엇인가요?

 

 

1. 들어가며

 

call by value : 값에 의한 전달
call by reference : 참조에 의한 전달
call by address : 주소에 의한 전달

 

결론부터 이야기하면 위와 같습니다. 처음에 들으면 쉽군! 하지만 공부를 하다보면 분명 헷갈리는 지점에 도달합니다. 예를 들어 Java는 Call by reference가 없다! 와 같은 것입니다. 어라? 함수 인자로 객체를 넘겨주고 값을 바꾸면 반영이 되지 않나..? 하지만 Java는 분명 call by value 만을 사용하고 있습니다. 본 글에서는 셋의 차이를 확실히 짚고 넘어가고자 합니다.

 

2. call by value와 call by referece, call by address의 차이가 무엇인가요?

 

2.1 call by value

 

call by value 는 말그대로 값의 의한 전달 입니다. 그렇기 때문에 함수로 값을 전달하면 그 값이 함수의 매개변수에 복사가 되며 함수 내에서 값을 아무리 바꿔도 원본의 값은 바뀌지 않습니다.

즉 함수가 실행이 되면 함수 stack frame에 원본 값을 복사하여 붙여넣고 그 변경은 그 stack 내부에서만 이루어지게 됩니다.

 

2.2 call by reference

 

함수 호출 시 parameter를 원본 데이터 값의 주소로 참조하고 있는 것을 의미합니다. c++을 제외하고서는 대부분의 언어에서 call by reference는 사용되지 않습니다.

 

void test(int& pRef) {
	pRef = 20;
}

int main(void) {
	int num = 0;
    int& ref = num;
    
    cout << ref << endl;
    test(ref);
    cout << ref << endl;
    
    return 0;
]

 

위에서 ref는 test 함수에서 할당한 20으로 값이 바뀝니다.

 

주의!

call by reference는 call by address와 혼동하여 자주 사용되곤 합니다. java에서는 call by value 만을 사용하고 있으며 우리가 call by reference라고 생각하는 부분들은 call by address를 통해 역참조를 하여 바꾸는 방식일 뿐입니다. (call by address는 call by value의 일종입니다.) 예를 들어 java의 경우 객체를 함수의 인자로 넘긴다면 그 주소값을 넘겨줄 뿐입니다. 따라서 calle 함수에서 넘겨받은 인자에 다른 값을 대입해도 stack frame에서만 변경에 일어나고 caller 함수에서는 변경이 일어나지 않습니다. Class.attribute = n 과 같이 참조에 의해 값을 변경하는 경우도 c에서 포인터로 역참조하여 값을 바꾸는 것과 같은 원리로 call by value입니다. call by addess의 경우 하기에 설명하겠습니다.

 

2.3 call by address

 

call by address는 call by value의 일종으로 함수의 인자에 값 대신 주소를 넘겨주는 것을 말합니다. 즉 값을 넘기느냐 주소를 넘기느냐의 차이만 있고 크게 보면 모두 call by value라고 할 수 있습니다. 대부분의 언어에서는 이 주소를 역참조하여 원본 데이터를 수정할 수 있도록 지원하고 있습니다.

 

예를 들어 java에서 함수 인자에 객체를 넣어서 보낸다고 해볼까요. 해당 객체를 넘겨받은 함수에서 해당 인자에 다른 객체를 할당한다면 그 객체를 넘겨준 함수에 할당되어 있던 객체가 바뀔까요? 정답은 당연히 아닙니다. 이는 우리가 call by value에서 살펴본 것과 동일한 것을 알 수 있습니다. 우리가 객체의 값을 바꿀 수 있던 것은 객체를 넘길 때 그 주소값을 넘겨주기 때문에 해당 주소값을 역참조하여 해당 객체 내부에 있는 값들을 바꿀 수 있던 것입니다. call by ~ 는 함수의 호출 방식에 대한 정의라는 걸 잊지 말아주세요!