2021-04-15 update log: 기존에 사용한 예제가 C언어 스타일이라서, C++ 스타일의 예제 코드를 추가하였습니다.
함수에 Argument(아규먼트)를 전달하는 방법에는 2가지 가 있습니다. 값을 전달하는 방법과 참조를 전달하는 방법이 있는데요. 많은 곳에서 call by value, call by reference라는 이름으로 한 번쯤 보신 적이 있을 겁니다.
call by value와 call by reference 차이점
call by value라는 건 Argument(인자)의 값을 그대로 함수의 Parameter(매개변수)에 복사를 해서 사용하는 방법이고, call by referece는 Argument의 참조만 복사를 해서 함수의 Parameter로 사용하는 것을 말합니다.
저의 이해를 바탕으로 그림을 그려봤습니다.
call by value로 호출할 때 전달되는 Argument는 원본인 데이터 "A"는 복사가 되어 새로운 "A"가 함수로 들어가게 됩니다. 그래서 함수 안에서 Parameter에 어떤 수정을, 여기서는 Parameter를 "B"로 수정을 했는데요, 한 Parameter는 복사된 새로운 데이터기 때문에 원본에는 아무런 영향을 미치지 못했습니다.
반면, call by reference로 호출하게 되면 함수에 어떤 값이 복사되어 들어가는 건 동일하지만 데이터 값이 아니라 원본 데이터인 "A"가 저장된 주소 값(#1)이 복사가 되어 전달이 된다는 점이 차이점입니다. 함수 내부에서 Parameter를 "B"로 수정하는 동작을 수행할 때 전달된 주소 값으로 데이터에 접근을 하기 때문에 #1 주소의 Argument 자체가 변경이 되게 됩니다. (call by reference와 call by address의 차이에 대해서는 무시하였습니다.)
call by Value 예시
// 예제 함수입니다.
void func(int x)
{
x = 2;
}
void CMyFirstProgramDlg::OnBnClickedButton1()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
// ↓↓↓ << 실습용 코드가 시작되는 위치 입니다. >> ↓↓↓
// ------------------------------------------------------
int i = 1;
func(i);
myprint(i);
// ------------------------------------------------------
// ↑↑↑ << 실습용 코드가 끝나는 위치 입니다. >> ↑↑↑
UpdateData(FALSE);
}
복사된 값이 Parameter로 전달되었기 때문에 원본은 변경되지 않아서 '1'이라는 결과가 나옵니다.
call by Reference 예시
C++ 스타일
void func(int& x)
{
x = 2;
}
void CMyFirstProgramDlg::OnBnClickedButton1()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
// ↓↓↓ << 실습용 코드가 시작되는 위치 입니다. >> ↓↓↓
// ------------------------------------------------------
int i = 1;
func(i);
myprint(i);
// ------------------------------------------------------
// ↑↑↑ << 실습용 코드가 끝나는 위치 입니다. >> ↑↑↑
UpdateData(FALSE);
}
C 스타일
void func(int *x)
{
*x = 2;
}
void CMyFirstProgramDlg::OnBnClickedButton1()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
// ↓↓↓ << 실습용 코드가 시작되는 위치 입니다. >> ↓↓↓
// ------------------------------------------------------
int i = 1;
func(&i);
myprint(i);
// ------------------------------------------------------
// ↑↑↑ << 실습용 코드가 끝나는 위치 입니다. >> ↑↑↑
UpdateData(FALSE);
}
두 코드 모두 결과는 아래와 같이 동일합니다.
함수는 Argument의 값을 포인터로 원본을 수정하여 결과는 '2'가 되었습니다.
결론
함수 호출 시 Argument의 전달방법 2가지를 비교해 봤습니다. call by value와 call by reference의 차이점을 다른 말로 표현한다면, 함수가 외부의 변수에 영향을 줄 수 있느냐 없느냐의 차이라고 할 수 있습니다. 기능적인 차이점을 바탕으로 용도에 따라서 적절한 방법을 선택하여 사용을 하면 되는데요. 이때 고려해야 할 한 가지 특징이 더 있습니다. 바로 함수의 수행 속도입니다.
구글링을 해 보면 call by reference의 속도적인 이점을 실험적으로 설명한 많은 글들을 쉽게 찾을 수 있습니다. 동작의 방식을 생각해보면 당연한 결과입니다. call by reference는 원본 데이터의 크기에 관계없이 해당 데이터의 포인터만 아규먼트로 전달하기 때문에 실제로 복사되는 크기가 작아서 속도에 이점을 가지게 됩니다. 그리고 함수로 구성했다는 것 자체가 반복 사용을 전재하고 있기 때문에 함수의 사용 빈도가 많아지면 많아질수록 그 차이는 더 커지게 되는 것이죠.
그렇다고 무조건 call by reference를 쓰는 게 좋은가 하면 그렇지만은 않겠죠. 함수라는 것은 논리적 경계를 만듦으로써 코딩 시 작업의 효율을 높이고자 하는데 그 목적이 있기 때문에 이런 특징을 고려하지 않고 남용되는 call by reference는 오히려 프로그램에 치명적인 오류를 야기할 수 있다는 점을 유의해야 하겠습니다.
끝!
'Software > C++&MFC 핵심노트' 카테고리의 다른 글
[C++/MFC 핵심노트] Function(함수) (2) | 2019.11.06 |
---|---|
[C++/MFC 핵심노트] Class (클래스) 접근범위 제한 - PART 2 (270) | 2019.01.10 |
[C++/MFC 핵심노트] Class (클래스) 정의,선언 - PART 1 (2) | 2018.11.19 |
[C++/MFC 핵심노트] C++언어의 기본구문 - 분기, 반복 (0) | 2018.11.13 |
댓글