[0]
함수 호출 시에 매개변수 전달 방법으로 pass-by-value와 pass-by-reference의 차이점에 대해 알아본다. 또한 왜 대다수의 언어들이 pass-by-value를 채택하였는지를 고찰해본다.
[1] pass-by-value
함수 호출 시에 매개변수의 값을 복사하여 전달한다. 여기서 가장 중요한 것은 값을 복사한다는 점이다.
void add(int num){
num++;
}
int main(void){
int val = 10;
add(val); // val is copied on call stack, and passed to add()
}
위 함수 호출에서 10을 지니고 있는 val의 값은 복사되어 add의 콜 스택에 저장되고, add함수로 전달된다. 따라서 add 내부의 num값을 아무리 변경하더라도 원래의 val 값을 영향을 줄 수 없다.
C에서는 오직 pass-by-value를 이용해서 함수를 호출할 수 있다. 간혹 가다 포인터를 매개변수로 넘겨주는 것을 pass-by-reference로 가르치는 경우가 있는데 이는 명백한 오류이다.
void add(int *num){
(*num)++;
}
int main(void){
int val = 10;
int *p = &val;
//both calls are same
add(&val);
add(p);
}
위에서 &val로 호출하였을때 add()에서 val의 값을 변경할 수 있다. 이 때문에 혼동이 발생하는데, 잘 생각해보면 add()의 인자로 넘겨준 것은 val이 아니라 val을 가리키는 포인터이고, 이는 &val을 넘겨주든 p를 넘겨주든 동일하다. 그리고 이것은 pass-by-value이기 때문에 넘겨준 포인터 p의 값(=가리키는 대상)을 변경할 수 없다.
[2] pass-by-reference
함수에게 변수를 복사하여 넘기는 것이 아니라, 변수의 레퍼런스를 넘겨준다. 따라서 함수 내부에서 변수의 값을 수정할 수 있다.
void add(int &num){
num++;
}
int main(void){
int val = 10;
add(val); // reference of val is passed to add()
}
c와 달리 c++에서는 pass-by-reference를 지원한다. 위의 코드에서는 val의 레퍼런스를 인자로 전달하기때문에, add함수의 결과가 외부의 val변수에도 적용된다. c++에서 레퍼런스와 포인터의 차이는 이전 포스팅을 참고하자.
[3] pass-by-assignments
python에서 사용하는 위 두 방식의 혼합이라고 생각하면 된다. mutable한 오브젝트면 pass-by-reference방식으로, immutable한 reference면 pass-by-value방식으로 동작한다. (python에선 모든 type을 오브젝트로 취급한다) 자세한 설명은 스택오버플로의 훌륭한 설명을 참고하자.
[4]
대부분의 언어에서 pass-by-value를 사용하거나, pass-by-reference를 부분적으로만 사용한다. 그 이유는 pass-by-value가 조금 더 안전하기 때문이다. 함수/메소드에 변수를 넘겨줄 때 해당 변수의 값이 변경되는 side effect 걱정할 필요가 없다. 물론 해당 함수의 동작을 완벽히 이해한다면, 이런 걱정이 필요가 없겠지만, 커널과 같은 대규모 프로젝트에서는 사실상 불가능하다. 그렇기 때문에 매개변수의 값이 변경되는지 안되는지를 명시적으로 표현하는 call-by-value가 훨씬 더 선호된다.
[참고]
https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference
'Computer Science > General' 카테고리의 다른 글
함수형 프로그래밍 (0) | 2020.09.13 |
---|---|
비동기적(asynchronous) 실행과 동기적(synchronous) 실행의 차이 (0) | 2020.02.20 |
Container와 VM의 차이 (0) | 2019.12.16 |
메모리 : 힙과 스택의 차이 (0) | 2019.10.15 |
c++에서 레퍼런스와 포인터의 차이 (0) | 2019.09.22 |