참조자와 함수
이전 글에서 단순히 변수에 별칭을 붙여주는 것으로 예를 들었는데, 참조자는 보통 함수에서 사용할 때 큰 장점을 보인다.
값을 변경하는 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;
⑤ 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 |