관리자 글쓰기
C++ 포인터3
2022. 3. 31. 17:39 - pingu-s

인수와 참조

 

참조

 

포인터를 함수의 인수로 사용하면 호출 장소의 변수를 변경할 수 있다. 그러나 포인터는 메모리 상의 주소를 직접 취급한다는 점에서 어려운 면이 있다. 그래서 이번에는 더욱 새로운 참조(reference)라는 기능을 학습하는 것으로 한다. 우선 참조에 관해 기본적인 내용을 학습한다. 참조는 변수 등으로 초기화한 식별자를 말한다. 형명에 &를 붙여 선언한다.

 

[구문 : 참조]

형명 &참조명 = 변수; //변수명에는 식별자를 사용한다

 

구문만으로는 알기 어렵기 때문에 실례로 참조를 사용해 보는 것으로 한다.

int a;
int &rA = a; //참조 rA를 변수 a로 초기화한다

이 코드의 'rA'를 변수 a로 초기화한 것이다. 참조를 사용한 간단한 예를 살펴보도록 한다.

 

예제) 참조를 사용해서 변수의 값 변경

참조 변수를 이용하여 값을 변경하는 코드를 작성해 보도록 한다.

#include <iostream>
using namespace std;

int main()
{
	int a = 5;
	int& rA = a;

	cout << "변수 a의 값은 " << a << "입니다.\n";
	cout << "참조 A의 값은 " << rA << "입니다.\n";

	rA = 50;

	cout << "rA에 50을 대입했습니다.\n";
	cout << "참조 rA의 값은 " << rA << "으로 변경하였습니다.\n";
	cout << "변수 a의 값도 " << a << "으로 변경하였습니다.\n";
	cout << "변수 a의 주소는 " << &a << "입니다.\n";
	cout << "참조 rA의 주소도 " << &rA << "입니다.\n";

	return 0;
}

상기의 출력 결과를 보면 알 수 있는 것처럼 참조 rA의 값과 주소는 변수 a와 똑같다. 참조 rA를 변수 a로 초기화함으로써 rA는 a와 같은 것이라고 지정하는 것이다.

rA ↔ a

  같다

로 된다. 그래서 포인터일 때와 똑같이 생각해 보자. 이것으로부터

rA = 50; ↔ a = 50;

          같다

라는 것이다. 즉, 위 예제와 같이 참조 rA를 사용하면 변수 a의 값을 변경할 수 있다. 참조 rA를 사용해서 변수 a를 취급할 수 있는 것이다.

 

단, 참조는 반드시 참조의 대상이 되는 변수로 초기화해 두어야 한다.

int &rA
rA = a; //참조에 대입할 수 없다

와 같이 뒤에서 대입할 수는 없다.

 

인수에 참조를 사용

 

이것으로 참조를 사용해서 이전의 swap() 함수를 포인터를 사용하지 않고 정의할 수 있다. 참조를 사용해서 새로운 swap() 함수를 기술해 보도록 한다.

 

예제) 함수의 인수로 참조 사용

인수가 있는 함수 swap()으로 참조를 사용해서 두 변수의 값을 교환하는 코드를 작성해 보도록 한다.

#include <iostream>
using namespace std;

//swap 함수의 선언
void swap(int& x, int& y);

int main()
{
	int num1 = 10;
	int num2 = 20;

	cout << "변수 num1의 값은 " << num1 << "입니다.\n";
	cout << "변수 num2의 값은 " << num2 << "입니다.\n";
	cout << "변수 num1과 num2의 값을 바꿉니다.\n";

	swap(num1, num2);

	cout << "변수 num1의 값은 " << num1 << "입니다.\n";
	cout << "변수 num2의 값은 " << num2 << "입니다.\n";

	return 0;
}

//swap 함수의 정의
void swap(int& x, int& y)
{
	int tmp;
	tmp = x;
	x = y;
	y = tmp;
}

참조를 인수로 한 swap() 함수를 사용하면 변수 num1과 변수 num2를 그대로 실인수로서 전달할 수 있다. 즉, 참조인 가인수(x, y)는 실인수(num1, num2)로 초기화된다. 이 초기화는

x (가인수 측)
같음
num1(실인수 측)
y (가인수 측)
같음
num2(실인수 측)

를 의미한다. 아래의 그림을 살펴보도록 한다. 여기서는 가인수를 교환하면 실인수도 교환되는 것을 나타내고 있다. 따라서 참조를 사용하면 포인터를 인수로 했을 때와 똑같이 가인수를 변경하면 실인수의 값을 변경할 수 있다.

 

함수의 호출(참조)

 

이와 같이 참조는 포인터와 똑같은 기능을 가진다. 그러나 참조는 포인터와는 다른 개념이므로 포인터에 참조를 대입하는 것은 할 수 없다.

 

실인수를 변경하고 싶지 않은 경우에는?

 

그런데 포인터와 참조를 사용해도 반드시 실인수를 변경할 필요는 없다. 함수의 내용에 따라서는 포인터와 참조를 사용해도 실인수를 변경하고 싶지 않은 경우도 있다.

이와 같은 때에는 함수 내에 실인수의 값을 변경하지 않는 것을 분명히 하기 위해 가인수에 const라는 지정을 붙인 것도 있다.

void func1(const int *pX);
void func2(const int &x);

상기의 코드는 실인수를 변경하지 않는 것을 명시한 함수 프로토타입 선언이다.

 

const를 사용한 경우, 함수 내에 인수를 변경하는 처리를 기술하면 오류로 된다.

void func1(const int* pX)
{
	cout << *pX << "을 출력합니다.\n";

	//*pX = 10; //실인수를 변경할 수 없게 된다.
}
void func2(const int& x)
{
	cout << x << "을 출력합니다.\n";

	//x = 10;
}

이 func1() 함수, func2() 함수 내에서는 인수를 변경할 수 없다.

const는 지정해도 되고 하지 않아도 상관없다. 그러나 지정함으로써 실인수를 변경하지 않는 것을 분명히 나타낼 수 있고 오류가 발생하기 어려운 코드를 작성할 수 있다.

 

 

출처: 박흥복서정희. 2015. C++ 프로그래밍 (초보자를 위한). 문운당

'개발 > C++' 카테고리의 다른 글

C++ 배열2  (0) 2022.04.05
C++ 배열  (0) 2022.04.04
C++ 포인터2  (0) 2022.03.30
C++ 포인터  (0) 2022.03.27
C++ 함수3  (0) 2022.03.26