본문 바로가기

Programming Languages/C++

[함수]-인수의 전달-참조 호출

값 호출과는 달리 참조 호출은 실 매개변수의 참조, 즉 주소를 전달한다. 이에 따라 형식 매개변수는 전달되는 실 매개변수의 별명처럼 사용된다. C 언어에서는 참조 호출 방식을 제공하지 않기 때문에, 참조 호출이 필요할 때는 포인터를 전달하는 방법을 사용하였다. 그러나 C++ 언어에서는 참조형을 사용 할 수 있다.

다음 프로그램은 참조 호출을 사용하는 함수를 사용하는 예이다.

// 소스코드 3-5 : SwapInt.cpp

#include <iostream>
using namespace std;
void SwapValues(int& x, int& y); // 원형

int main() {
	int a, b;
	cout << "두 수를 입력하세요 : ";
	cin >> a >> b;
	if (a < b) SwapValues(a, b); // 순서를 바꿔 a에 큰 값을 넣음
	cout << "큰 수 = " << a << " 작은 수 = " << b << endl;
	return 0;
}
// 두 변수의 값을 바꾸는 함수 
// 인수 int &x, int &y : 값을 바꿀 변수
// 반환 : 없음
void SwapValues(int& x, int& y) {
	int temp = x;
	x = y;
	y = temp;
}

====== 결과 ======
두 수를 입력하시오 : 50 100
큰 수 = 100 작은 수 = 50

SwapValues()는 형식 매개변수로 전달되는 실 매개변수의 값을 서로 바꾸는 처리를 하는 함수이다. 두 매개변수는 int의 참조형으로 선언되어 있다. 따라서 SwapValues()를 호출할 때 매개변수 x와 y는 실 매개변수의 참조를 전달받아, x와 y를 사용하는 것은 해당되는 실 매개변수를 직접 사용하는 것과 같은 동작을 하게 된다. 즉, SwapValues(a, b)라고 호출하면 x는 a, y는 b를 사용하는 것과 동일하다. 따라서 SwapValues()에서 x와 y의 값을 바꾸는 것은 a와 b의 값을 서로 바꾸는 것과 동일한 동작을 하게 된다. 

이 함수는 두 변수의 값을 서로 바꾸는 것이 목적이며 특별히 반환할 값이 없다. 그러므로 이 함수는 void형으로 선언되어 있고, 이러한 함수는 return 명령으로 값을 반환하는 문장을 사용할 수 없다. 

※ 주의 ▶ 참조변수의 참조 대상

참조변수는 포인터와 같이 다른 대상을 참조하는 것이므로 자료형이 일치해야 한다.

int iVar;
double dVar;
int &iRef1 = iVar; // 1. 자료형이 일치함
int &iRef2 = dVar; // 2. 오류 - 자료형이 일치하지 않음
int &iRef3 = 10;   // 3. 오류 - l-value를 참조해야 함;
const int &iRef4 = dVar; // 4. 가능
const int &iRef5 = 10;   // 5. 가능

위 문장들 중에서 1은 자료형이 일치하므로 올바른 문장이다. 그러나 2는 int형 참조변수로 double형을 참조하도록 하고 있다. 만일 이것을 허용하면 iRef2를 이용하여 dVar의 값을 읽을 때 원래 dVar 값과 논질적으로 일치하지 않는 값을 읽게 된다. int와 double의 데이터 표현 방법이 다르기 때문이다. 쓰기의 경우에도 마찬가지이다. 그러므로 2와 같은 문장은 허용하지 않으며, 컴파일 과정에서 문법 에러가 발생한다. 또한 참조변수가 상수 참조가 아니라면 그 참조변수를 이용하여 쓰기가 가능해야 하므로 참조하는 것은 l-value이여야 하며, 3과 같은 참조를 할 수 없다. 이와 같은 이유로 [소스코드 3-5]에서 정의한 함수 SwapValues()를 다음과 같이 호출할 수는 없다.

int a{1};
double c{1.5};
SwapValues(a, c); // c가 int형이 아님
SwapValues(a, 10); // 상수 10은 l-value가 아님

반면 const 참조는 4나5와 같이 참조 대상이 l-value가 아니더라도 묵시적 형 변환이 가능하다면 다른 자료형의 변수나 수식을 사용할 수도 있다.