본문 바로가기

C++

[C++] 참조자(Reference)와 함수

참조자와 함수

이전 글에서 단순히 변수에 별칭을 붙여주는 것으로 예를 들었는데, 참조자는 보통 함수에서 사용할 때 큰 장점을 보인다.


값을 변경하는 Swap 함수를 Call-by-value의 형태로 정의하면 아래와 같다.

#include <iostream>

using namespace std;

void Swap(int val1, int val2) {
	int temp = val1;
	val1 = val2;
	val2 = temp;
}

int main() {
	int val1 = 5;
	int val2 = 10;

	Swap(val1, val2);

	cout << "val1 : " << val1 << endl;
	cout << "val2 : " << val2 << endl;

	return 0;
}


Swap 함수의 매개변수에는 값이 복사되기 때문에 val1과 val2의 값은 서로 바뀌지 않는다.

하지만 참조자를 이용하여 Call-by-reference의 함수 호출을 진행하면 두 값이 서로 바뀌는 것을 볼 수 있다.


#include <iostream>

using namespace std;

void Swap(int &ref1, int &ref2) {
	int temp = ref1;
	ref1 = ref2;
	ref2 = temp;
}

int main() {
	int val1 = 5;
	int val2 = 10;

	Swap(val1, val2);

	cout << "val1 : " << val1 << endl;
	cout << "val2 : " << val2 << endl;

	return 0;
}

매개변수로 값을 넘길 때,  int &ref1 = val1;  이 실행된다고 생각하면 쉽다.

ref1과 ref2는 또 다른 메모리에 할당된 변수가 아닌, val1, val2의 다른 이름이므로 실제로 값 복사가 이뤄진다.



반환형이 참조형인 경우

반환형을 참조형으로 정의하는 것도 가능하다.

#include <l;iostream>

using namespace std;

int& RefRetFuncOne(int &ref) {
	ref++;
	return ref;
}

int main() {
	int val1 = 1;
	int &val2 = RefRetFuncOne(val1);

	val1 += 1;
	val2 += 100;

	cout << "val1 : " << val1 << endl;
	cout << "val2 : " << val2 << endl;

	return 0;
}

결과



val1와 val2가 같은 값으로 출력되는 이유는 참조형으로 반환된 값을 참조자에 저장했기 때문이다.


① int val1 = 1;


② RefRetFuncOne(val1); 호출


③ int &ref = val1;


④ ref++;


⑤ int &val2 = RefRetFuncOne(val1);

(ref는 지역변수로, 함수의 반환으로 인해 소멸된다.)


⑥ val1 += 1;

     val2 += 100;


두 변수 모두 같은 값을 가리키고 있으므로, 그 값은 동일하게 103이 된다.



하지만 반환형이 참조형이어도, 참조자로 받지 않으면 결과가 달라진다.

#include <iostream>

using namespace std;

int& RefRetFuncOne(int &ref) {
	ref++;
	return ref;
}

int main() {
	int val1 = 1;
	int val2 = RefRetFuncOne(val1);

	val1 += 1;
	val2 += 100;

	cout << "val1 : " << val1 << endl;
	cout << "val2 : " << val2 << endl;

	return 0;
}

int val2 = RefRetFuncOne(val1);

참조자로 받지 않으면, num2는 별도의 다른 변수가 된다.

따라서 위와 같은 결과가 나오지 않는다.


결과




※ 주의


1. 지역변수를 참조형으로 반환하는 경우

지역변수를 참조형으로 반환, 참조자로 받게 되는 경우 문제가 있다.

위 예제에서 본 것과 같이, 지역변수는 함수가 반환되면 소멸된다.

따라서 참조자로 받게 되는 경우, 찌꺼기의 형태로 남아있는 데이터를 참조하게 되어 이상한 출력 결과가 나올 수 있다.

#include <iostream>

using namespace std;

int& RefRetFuncOne(int n) {
	int num = 10;
	num += n;
	return num;
}

int main() {
	int &val1 = RefRetFuncOne(10);

	cout << "val1 : " << val1 << endl;

	return 0;
}


결과




2. const 참조자 사용

const 선언으로 변수를 상수화한 후, 참조자를 통해 값을 변경하는 작업은 불가능하다.


(X)

const int num = 20;
int &ref = num;
ref += 10;

상수화된 변수에 대한 참조자 선언은 다음과 같이 해야 한다.


(O)

const int num = 20;
const int &ref = num;


(O)

C++에서는 const 참조자를 이용해서 상수를 참조할 때 임시변수를 만든다.

그리고 이 장소에 상수 30을 저장하고, 참조자가 이를 참조하게끔 한다.

const int &ref = 30;


따라서 함수 내 매개변수를 const 상수화 시키는 것도 가능하다.

값이 변하면 안되는 매개변수에 const를 선언하면 실수로 발생하는 버그를 줄일 수 있다.

int Adder(const int &num1, const int &num2) {
	return num1 + num2;
}


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

[C++] 구조체  (0) 2019.03.08
[C++] new & delete  (0) 2019.03.08
[C++] 참조자(Reference)  (0) 2019.03.05
[C++] 기본 자료형  (0) 2019.03.05
[C++] 인라인(inline) 함수  (0) 2019.03.04