본문 바로가기

Programming Languages/C++

[함수]-인수의 전달-const 매개변수

참조 호출을 하거나 매개변수가 포인터인 경우 함수 내에서 호출 루틴의 실 매개변수를 수정할 수 있다. 그러나 이러한 방식의 호출을 했다고 해도 실 매개변수의 값을 보호하고 싶을 때에는 해당 형식 매개변수를 const로 지정하면 된다.

이러한 형태의 매개변수는 데이터의 크기가 큰 인수를 전달할 때 유용하게 사용할 수 있다. 만일 이러한 데이터를 값 호출 방식으로 전달하면 이를 복사하기 위해 많은 시간이 소비되며, 메모리도 많이 소비된다. 이런 경우에는 참조 호출을 이용하는 것이 바람직하다. 그러나 참조 호출을 하면 호출한 루틴에서 전달한 인수가 함수를 실행한 후 원래의 값을 유지하고 있다는 것을 보장받지 못한다. 이때 실 매개변수의 값이 변경되지 않음을 보장하기 위해 함수의 형식 매개변수에 const를 지정할 수 있다.

// 소스코드 3-6 : PrintRec.cpp

#include <iostream>
using namespace std;

struct SalesRec
{
	char pID[10];
	int dYear, dMonth, dDate;
	char deliverAddr[40];
};

void PrSalesRec(const SalesRec& srec);

int main() {
	SalesRec s = { "C25TV001", 2019, 11, 15, "서울시 종로구 대학로86" };
	PrSalesRec(s);
	return 0;
}

void PrSalesRec(const SalesRec& srec) // srec은 상수 인수
{
	cout << "품목코드 : " << srec.pID << endl;
	cout << "배달일자 : " << srec.dYear << "년 ";
	cout << srec.dMonth << "월 ";
	cout << srec.dDate << "일 " << endl;
	cout << "배달주소 : " << srec.deliverAddr << endl;
}

====== 결과 ======
품목코드 : C25TV001
배달일자 : 2019년 11월 15일
배달주소 : 서울시 종로구 대학로86

위의 PrintRec.cpp에서 SalesRec형의 구조체는 62바이트의 데이터를 저장한다. 이 구조체를 값 호출로 전달하려면 62바이트의 데이터를 복사해야 하지만, 참조 호출로 전달하는 경우에는 인수의 참조만 전달하면 되므로 훨씬 효율적으로 호출할 수 있다. void PrSalesRec(const SalesRec& srec); 에서 형식 매개변수 srec은 참조형이며, const가 지정되어 있다. 이는 srec이 참조하는 값이 PrSalesRec()을 실행하는 동안 바뀌지 않는다는 것을 의미한다. 이러한 const 매개변수는 참조 호출뿐만 아니라 포인터를 포함하는 매개변수에 대해서도 동일한 목적으로 사용할 수 있다. 또한 기본적으로 참조 호출이 된다고 할 수 있는 배열에 대해서도 같은 목적으로 사용할 수 있다. 주의할 것은 const가 지정되지 않은 변수를 const가 지정된 형식 매개변수에 전달하는 것은 문제가 없으나, const가 지정된 변수를 const가 지정되지 않은 형식 매개변수에 참조 호출로 전달하는 것은 허용되지 않는다는 것이다. 

// 소스코드 3-7

void RtnA(int x);
void RtnB(int &x);
const int a = 10;

RtnA(a);                    // OK
RtnB(a);                    // Error! - const 변수를 const가 아닌 참조 인수에 전달
RtnB(const_cast<int&>(a));  // OK - const 한정어를 해제

위 소스코드에서 RtnA(a)는 값 호출로 인수 전달을 하므로 문제가 없다. 그러나 RtnB(a)는 const 변수 a를 const가 아닌 형식 매개변수에 참조 호출 방식으로 전달하였고, 만일 이를 허용한다면 RtnB()에서 형식 매개변수인 x의 값을 변경할 경우 const인 a의 값이 변경되어야 하는 모순이 발생한다. 따라서 이런 호출은 허용되지 않는다.

const_cast는 const 한정어를 해제함으로써 const 객체를 const가 아닌 참조형 매개변수에 인수로 전달할 수 있게 한다. RtnB(const_cast<int&>(a)); 에서 a의 const 한정어를 해제한 int&형으로 형 변환되어 RtnB()를 호출할 수 있게 된다.