DevNote

참조자(reference) 본문

C++

참조자(reference)

Ahnda 2020. 2. 17. 17:39

 C와 다르게 C++에는 특정 변수의 실제 이름 대신에 사용할 수 있는 참조자(reference)라는 새로운 기능이 추가되었다. 참조자는 크기가 큰 구조체나 클래스의 데이터를 함수의 인수로 줘야 할 경우나 클래스를 설계할 때 자주 사용된다.

 


<레퍼런스 선언>

int x;		// 변수 선언
int& rx = x;// 레퍼런스 선언

 위의 예제를 보면 &연산자는 주소 연산자가 아니라 타입 식별을 위한 식별자로 사용된다. 즉, int&는 int형 변수에 대한 참조를 의미한다. 이렇게 선언된 참조자는 대상 변수와 같은 메모리 위치를 참조한다.

 

<레퍼런스 사용 주의사항>

1. 레퍼런스의 타입은 대상이 되는 변수의 타입과 일치! 
2. 선언과 동시에 초기화 
3. 한 번 초기화되면, 참조 대상 변경이 불가능

 

<예제>

#include <iostream>
using namespace std;

int main()
{
	int x = 10;	// 변수 선언
	int& rx = x;	// 레퍼런스 선언

	cout << "x : " << x << endl;
	cout << "rx : " << rx << endl;
	
	rx++;			// reference를 이용한 증가연산

	cout << "x : " << x << endl;
	cout << "rx : " << rx << endl;

	cout << endl;

	cout << "x의 주소값 : " << &x << endl;
	cout << "rx의 주소값 : " << &rx << endl;

	return 0;
}

<결과>

 위의 예제와 결과를 통해 레퍼런스를 이용해 증가 연산을 수행하면, 참조 변수뿐만 아니라 대상 변수도 같이 변경됨을 확인할 수 있다.

 


<함수의 인수로 전달>

 C++에서 레퍼런스는 주로 함수에 인수를 전달할 때 사용된다. 함수가 레퍼런스를 인수로 전달받으면, 레퍼런스가 참조하고 있는 실제 변수의 값을 함수 내에서 조작할 수 있기 때문이다. 아래의 예제는 call_by_reference를 이용해 두 변수를 swap하는 변수 입니다.

 

<예제>

#include <iostream>
using namespace std;

void swap(int& a, int& b)
{
	int temp;

	temp = a;
	a = b;
	b = temp;
}


int main()
{
	int A = 1, B = 28;
	cout << "A : " << A << "\t" << "B : " << B << endl;

	swap(A, B);
	cout << "A : " << A << "\t" << "B : " << B << endl;

	return 0;
}

<결과>

 

 위와 같이 call_by_reference는 레퍼런스뿐만 아니라 포인터(call_by_address)를 사용해도 똑같은 결과를 얻을 수 있다. 구문만 약간 다르게 수정(swap 함수인자를 int*형으로 바꾸고, 함수 내 int * temp로 선언 수정)하면 결과는 같게 나타난다. 다음은 call_by_reference의 특징이다.

 

  1. 함수 내에서 포인터(*)를 사용하지 않으므로, 함수 내부의 코드가 깔끔해진다..
  2. 함수의 호출이 call_by_value와 같은 형태가 되어, 코드를 읽기가 쉽지 않다.

따라서, 간단한 함수에서는 굳이 call_by_reference보다는 call_by_value가 더 좋을 수 있다. 또한, call_by_reference가 꼭 필요할 때엔 레퍼런스보다는 포인터를 이용하는 것이 더욱 직관적일 수 있다. 결국, 레퍼런스는 크기가 큰 구조체나 클래스를 다룰 때에만 사용하는 것이 좋다.

 


<구조체의 참조>

 C++에서 레퍼런스는 주로 구조체/클래스와 같은 사용자 지정 타입을 다룰 때 유용하다. 구조체를 참조하는 방법은 변수를 참조하는 방법과 같다.

 

<예제>

#include <iostream>
#include <string>
using namespace std;

struct A{

	string name;
	int size;
};


void Show(const A& a)
{
	cout << a.name << " 클래스의 크기는 " << a.size << "입니다." << endl;
}

int main()
{
	A a = { "초심자", 28 };
	Show(a);

	return 0;
}

<결과>

더보기

함수 내부에서 구조체를 직접 변경할 필요가 없을 때는 const 키워드를 이용해 원본 구조체에 대한 변경을 허용하지 않는 것이 좋다.

'C++' 카테고리의 다른 글

복사 생성자(copy constructor)  (0) 2020.02.15