반응형

오늘은 메모리에 관해 좀 재밌는 내용을 설명하겠다.
레퍼런스 변수는 원본과 같은 메모리 공간을 가리킨다고 지난 포스트에 설명했다.
(기억이 나지 않는다면 [제2장] C++ 기본 : Reference 포스트를 참고하시라~)

레퍼런스 변수를 리턴값으로 쓰기 위해선 원본이 메모리상에 보존되어야 한다.
무슨 말인고 하니... 레퍼런스 변수가 가리킨 값(원본)이 사라진다면
레퍼런스 변수 역시 의미가 없어지기 때문이다.

일단 정상적으로 돌아가는 아래 예제를 살펴보자.

#include < iostream >
using namespace std;

int& increment(int &val) // 레퍼런스 변수로 원본을 받음
{
 val++;
 return val;
}

void main()
{
 int n = 10;
 int &ref = increment(n); // 파라미터로 레퍼런스 원본으 넘겨줌

 cout << "n : " << n << endl;
 cout << "ref: " << ref << endl;
}

자... 누구나 예상할 수 있듯이 결과는 11이 출력된다.
왜냐하면 원본 변수 int n 은 레퍼런스 변수가 사용되는 동안 유지되기 때문이다.
10의 값이 함수 안에서 ++ 연산을 통해서 11이 되었고 그것을 출력하였다.

그럼 당연히 반대의 경우도 살펴봐야되지 않겠는가?
지역변수를 레퍼런스 변수로 리턴하는 경우를 살펴보자.

#include < iostream >
using namespace std;

int& function()
{
 int val=10; // 지역변수가 원본이 되었다
 return val;
}

int& function2() // 임의로 추가한 두번 째 함수
{
 int val2=20;
 return val2;
}

void main()
{
 int &ref = function(); // 레퍼런스 변수 ref의 원본은 function()의 지역변수이다
 int &ref2 = function2();

 cout << ref << endl;
}

자... 무엇이 출력될 것 같은가? - 주의 : 원본 소스에서 function2()가 추가되었다 -
언뜻 보면 ref는 function()의 지역변수 int val = 10; 로부터 참조하였으니 10을 출력할 것 같다.

하지만 이 소스는 20을 출력한다!
ref는 분명 function()에서 값을 받았는데... function2()의 20이 출력된다.
우째 이런 일이...!

자 이제부터 이유를 알아보자.
main()이 실행되면 프로세서에 int ret와 int ret2에 대한 메모리를 할당한다 (총 8바이트)
예를들어 ret가 메모리 8000번에, ret2가 8004번에 할당되었다고 가정한다.

ㅁㅁㅁㅁ ㅁㅁㅁㅁ
(ret)   (ret2)

다음 function()이 실행되면 함수 내 지역 변수를 할당하기 위해서 추가적으로 4바이트를 할당한다
그럼 val은 메모리 8008번에 할당된다.

ㅁㅁㅁㅁ ㅁㅁㅁㅁ ㅁㅁㅁㅁ
(ret)   (ret2)   (val)

이제 ret는 레퍼런스 리턴으로 val의 위치를 참조하게 된다. 이때 가리키는 값은 10 이다.
(지금 cout으로 출력하면 10이 출력된다)

자~ 이제 함수 function()이 종료되고 지역번수 val이 차지하는 메모리공간 8008은 사라진다.

ㅁㅁㅁㅁ ㅁㅁㅁㅁ
(ret)   (ret2)

그리고 function2()가 실행되면서 val2의 메모리가 8008에 할당된다.

ㅁㅁㅁㅁ ㅁㅁㅁㅁ ㅁㅁㅁㅁ
(ret)   (ret2)   (val2)

중요한 점은 ret가 아직도 8008번을 가리키고 있다는 것이다!
val2의 값은 20이 대입되었으니 이제 ret의 값을 출력하면 20이 출력된다.

이러한 이유로 지역변수를 레퍼런스로 리턴할 경우 뜻하지 않은 결과를 초래할 수 있다.
이런 버그는 참 찾기 힘드니 절.대.로. 이렇게 코딩하지 말자!

반응형

+ Recent posts