[열혈C++] Call-by-value? Call-by-reference?

Yoons·2023년 8월 6일
0
post-thumbnail

❗️Notice❗️

저의 velog에 작성된 글은 모두 저의 주관적인 생각 및 이해를 바탕으로 작성된 글이므로 
정확하지 않은 내용을 있을 수 있음을 알립니다.

[교재] 윤성우 열혈 C++ 프로그래밍

Intro

포인터와 참조자에 대해 배우고 함수를 정의해서 사용할 때 가장 중요한 개념 중 하나가 Call-by-value와 Call-by-reference라고 생각한다.

정의된 함수를 해석하다보면 이게 Call-by-value인지, Call-by-reference인지 헷갈리는 상황이 발생하는데, 오늘은 Call-by-value와 Call-by-reference를 구분하는 기준이 무엇인지에 대해 이야기 해보고자 한다.

우선 필자가 먼저 언급하고 싶은 부분은 "매개변수의 형태는 구분하는 기준이 될 수 없다." 라는 점이다.

이해를 돕기 위해 예를 들어보겠다.

int* SimpleFunc(int* ptr) { . . . }

위의 함수를 봤을 때 Call-by-value인지, Call-by-reference인지 구분할 수 있겠는가? 매개변수의 형태만 봐서는 "포인터로 받으니까.. Call-by-reference 아닐까?"라는 생각이 들 수도 있다.

위의 정답은 "그때그때 달라요."이다.

구분 기준에 대한 결론을 이야기 해주자면 '형태'로 구분하는 것이 아니라 '의미'로 구분하는 것이다.


1. Call-by-value

int* SimpleFunc(int* ptr) {
	return ptr+1;
}

위의 함수를 보자. ptr의 주소값을 *ptr로 받는다. 그리고는 ptr의 주소값을 +1해서 반환한다. 그렇다면 main 함수에서 ptr의 주소값이나 포인터값이 바뀌었는가?

그렇지 않다. 함수 내부에서 ptr+1 연산을 수행하기는 하지만, 이는 함수 내부에서만 이루어질 뿐, main 함수에서는 ptr의 주소값이 변하지 않는다.

*ptr의 값이 변하지 않는 것은 당연하다.

이것이 Call-by-value이다!


2. Call-by-reference

그렇다면 다음 함수는 어떨까?

int* SimpleFunc(int* ptr) {
	*ptr = 20;
    return ptr;
}

똑같이 ptr의 주소값을 *ptr로 받는다. 하지만 이 함수에서는 "*ptr=20;"을 통해서 주소값을 이용해 ptr에 저장된 값을 바꾸고 있다.

이는 주소값을 이용하여 외부(main)함수에 있는 변수에 접근하는 것이므로 Call-by-reference라고 할 수 있다.


Outro

기존에 다른 블로그를 통해 Call-by-value와 Call-by-reference에 대해 이야기를 듣고 본 내용을 보면 더 헷갈릴 수도 있다.

대부분의 블로그가 해당 내용을 설명할 때 가장 많은(대부분의) 예시가 Swap 함수이다. 이 또한 매우 좋은 예시이지만, 필자가 작성한 내용은 이보다 조금 더 헷갈릴 수 있는 예시이다.

독자에게 말해주고 싶은 결론은 "주소값을 통해 외부 변수값에 영향을 주는가?"가 Call-by-value와 Call-by-reference를 구분짓는 명확한 기준이 될거라는 이야기다.

왜냐하면 외부 변수값에 영향을 주지 않았다는 이야기는 함수 내부적으로 다른 변수에 값을 복사해서 사용했다는 이야기이고, 외부 변수값에 영향을 준다는 이야기는 함수 내부적으로 사용한 변수가 외부 변수의 주소값을 이용해서 사용했다는 반증이기 때문이다.

설명이 조금 어려웠을 수 있지만, 내용을 곡씹어 보며 궁금증을 해결하길 바란다. 혹시나 궁금하거나 잘못된 내용이 있다고 생각되면 여지없이 댓글을 달아주길 바란다!!

profile
모든 글은 저의 눈물을 머금으며 작성한 글이니..재밌게 봐주세요 :) 깃헙 맞팔@

0개의 댓글