참조자와 함수
Call-by-value와 Call-by-reference는 많이 들어봤을 것이다.
Call-by-value란 '값'을 인자로 전달하는 함수의 호출 방식, Call-by-reference란 '주소 값'을 인자로 전달하는 함수의 호출방식이다.
int main()
{
int a = 1;
int b = 2;
CallByValue(a,b);
CallByReference(&a, &b);
ReferenceFunction(a, b);
}
위와 같이 구성된 main함수가 있다고 가정하자.
⊙ Call-by-value!
void CallByValue(int num1, int num2)
{
num1 = 50;
num2 = 30;
}
CallByValue함수는 위와 같이 함수의 내부에서 a와 b의 값을 바꿔도 main함수의 a, b의 값은 바뀌지 않는다.
왜?
CallByValue함수의 인자값인 int num1와 int num2는 CallByValue라는 함수의 지역변수이다. 따라서 int num1과 int num2의 값을 바꿔도 해당 num1과 num2는 CallByValue함수가 끝나면 함께 사라지게 되는 것이다.
그래서 main함수의 a,b. 즉, 함수 외부에 선언된 변수에 접근이 불가하다.
그래서 필요한 것이 주소 값을 인자로 전달하는 Call-By-Reference이다.
⊙ Call-by-Reference
void CallByReference(int *num1, int *num2)
{
*num1 = 30;
*num2 = 50;
}
이렇게 되면 int *num1과 int *num2가 주소 값을 넘겨받아서 a와 b의 주소 값에 저장된 값을 '직접' 변경하게 되므로 함수 외부에 선언된 변수의 값을 바꿀 수 있는 것이다.
정리하자면 Call-by-Reference는 주소 값을 전달받아서, 함수 외부에 선언된 변수에 접근하는 형태의 함수 호출이다.
주소 값이 전달되었다는 사실이 중요한 것이 아닌 주소 값이 참조의 도구로 사용되었다는 사실이 중요한 것이며 이것이 Call-by-Value와 Call-by-Reference를 구분하는 기준이 된다.
Call-by-Value와 Call-by-Reference를 구분하는 기준에 대한 추가 설명
예를 들어
int *Test(int *ptr)
{
return ptr+1;
}
이 함수는 분명 인자값을 주소로 전달하고 있음에도 Call-By-Reference가 아닌 Call-By-Value이다.
왜냐하면 이 함수의 연산의 주체는 값이기 때문이다. 다만 그 값이 주소 값일 뿐인 것이다. 주소 값을 이용해 외부에 선언된 변수에 접근하는 Call-By-Reference와 거리가 멀다.
int *Test2(int *ptr)
{
*ptr = 20;
return ptr;
}
그러나 이런 식으로 사용되었다면 이 함수는 Call-By-Reference이다. 주소 값을 이용해서 함수 외부에 선언된 변수를 참조했기 때문이다.
C++에서는 함수 외부에 선언된 변수의 접근 방법으로 두 가지가 존재한다.
하나는 '주소 값'을, 다른 하나는 '참조자'를 이용하는 방식이다.
⊙ 참조자를 이용한 Call-By-Reference?
Call-By-Reference의 가장 큰 핵심은 함수 내에서 함수 외부에 선언된 변수에 접근할 수 있다는 것이었다.
void ReferenceFunction(int &num1, int &num2)
{
num1 = 10;
num2 = 20;
}
매개변수로 참조자가 들어와 있다. 참조자는 선언과 동시에 변수로 초기화가 되어야 하지 않나?라고 생각할 수 있다.
하지만 매개변수는 함수가 호출되어야 초기화가 진행되는 변수들이다. 즉, 초기화가 이뤄지지 않은 것이 아니라 함수 호출 시 전달되는 인자로 초기화를 하겠다는 의미이다.
이와 같은 코드는 포인터로 주소값을 넘겨받는 Call-By-Reference 보다 함수의 특성이 한눈에 파악되지 않는다는 단점이 존재한다. 참조자로 넘겨줄 때 함수는 ReferenceFunction(a, b)로 Call-By-Value함수와 동일해 보인다.
그러나 실제 함수 외부의 변수 값에 영향을 끼칠 수 없는 CallByValue함수와 달리 이 함수는 함수 외부의 값을 변경할 수 있으므로 이 함수 내부에서 어떤 일이 일어날 지 직관적으로 파악이 불가능하기 때문에 단점이라고 하는 것이다.
이 단점은 const를 사용함으로써 극복이 가능하다. 함수의 매개 변수 선언 시 const를 붙여줌으로써 함수 내에서 참조자를 이용한 값의 변경을 하지 않겠다고 선언하는 것이다.
이렇게 하면 함수 내부에서 참조자에 값을 저장하는 경우 컴파일 에러가 발생하며 함수의 원형만 봐도 값의 변경이 이루어지지 않음을 확신할수 있다.
'Study > C++ , C#' 카테고리의 다른 글
[C++] 클래스(Class)와 구조체(Struct)의 차이 (0) | 2020.01.15 |
---|---|
[C++] QueryPerformanceCounter / 프로그램 실행 시간 측정 (0) | 2020.01.15 |
[C++] 매크로 함수와 인라인 함수(Inline) (0) | 2020.01.10 |
[C++] new 와 delete (0) | 2020.01.10 |
[C++] 참조자란? (Reference) (0) | 2020.01.08 |