본문 바로가기

프로그래밍/C++

[C++] 이명제조기, 참조자 - 4 (with. 함수)

들어가며

시작하기에 앞서 드디어 본인이 현재 서식하고 있는 지역에서도 코로나 바이러스 확진자가 나왔다.

발이나 손은 반드시 외출 후 세척해야 한다.

신천지 신도라고 환자가 말해주었기에

천만다행으로 빠르게 역학조사가 실시 되었다.

지금 할 수 있는 최선의 방법은 외출을 자제하는 것이지 않을까.

 

참조형 반환(진) - 중

전 글의 끝 무렵에 코드를 주고 해석을 하고 의미를 찾아오라고 하였다.

우선 그 코드는 다음과 같다.

#include <iostream>

using namespace std;

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

int main()
{
    int num1 = 1;
    int num2 = RefRetFuncOne(num1);

    num1+=1;
    num2+=10;
    cout << num1 << endl;
    cout << num2 << endl;

    return 0;
}

 

그리고 위 코드의 실행 결과는 프로그램의 흐름이 다음과 같음을 증명한다.

그림 24 - 한 끗 차이

num2를 참조자에서 변수로 바꾸고 실행하니

새로운 변수가 선언과 동시에 초기화 된 상황이다.

 

이렇듯 반환형이 참조형인 경우, 반환된 값을 어떤 것으로 저장하느냐에 따라서

그 결과에 차이가 있음을 확인하였다.

따라서 적절하고 정확한 판단으로 선택해야 한다.

 

참조형 반환(진) - 하

이제 마지막으로 참조자를 반환하되,

반환형은 기본 자료형인 경우를 이해하기 위해

이전의 코드의 함수 반환형을

int& RefRetFuncTwo(int& ref)

다음과 같이 변경한 후에

int RefRetFuncTwo(int& ref)

 

실행시킨다면?

우선 두 코드의 차이는 무엇일까.

우선 알 수 있는 것은 함수의 반환형이 다르다는 것이다.

다른 차이점은 보이지 않는가?

정말 보이지 않는가?

유감이다.

안 속는군.

 

따라서 다음의 코드를 해석해보길 바란다.

#include <iostream>

using namespace std;

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

int main()
{
    int num1 = 1;
    int& num2 = RefRetFuncTwo(num1);

    num1+=1;
    num2+=10;
    cout << num1 << endl;
    cout << num2 << endl;

    return 0;
}

 

'뭐여, 실행 결과가 아까랑 똑같은 뎁쇼?'

정말 그렇게 생각하는가?

그림 25 - 쳇 (출처 - 강철의 연금술사)

 

뿐만 아니라 실행하였을 때의 과정이나 흐름 또한 [그림 24]와 동일하다.

반환형이 참조형인 'RefRetFuncTwo 함수' 는 반환 값을

다음과 같이 두 가지 형태로 저장할 수 있다.

그림 26 - 반환형이 참조형인 경우

 

그에 반에 반환형이 기본 자료형인 'RefRetFuncTwo 함수'는 반환 값을

반드시 변수에만 저장해야 한다.

그림 27 - 반환형이 기본 자료형인 경우

이유야 조금만 생각해 보면 합리적으로 추론할 수 있다.

반환 되는 값은 당연하게도 '상수(데이터)'나 다를 게 없지 않은가?

따라서 변수에 저장하는 것은 합당하다.

 

잘못된 참조의 반환

자 그럼 어느정도 개념적인 부분은 이해하였다.

하였다. 아무튼 했다.

그렇다면 이와 관련된 내용은 안 보고도 풀 수 있지 않겠는가?

안 보고 어떻게 문제를 푸는지 궁금한가?

나도 모르니까 알아서 잘 해보길 바란다.

아무튼 다음 코드를 보고 논리적으로 무엇이 잘못 되었는지 확인해보라.

int& RetRefFunc(int n)
{
    int num = 20;
    num += n;
    return num;
}

 

'음, 잘 모르겠는뎁쇼.'

얼핏보면 뭐가 잘못 된 것인지 잘 모를 수도 있을 것이다.

힌트를 주자면 '반환형과 반환값'이다.

'그래도 모르겠는뎁쇼.'

그림 26 - 답답해 죽는 매트

 

모르겠다고만 하지 말고 생각을 해보라.

목 위에 달려 있는 것이 원효 대사 전용 텀블러가 아니라면 말이다.

'와 선넘네, 말넘심;;'

그림 27 - 시무룩해진 독자

사실 본인도 답을 보기 전에는 똑같은 반응이었다.

나한테도 하는 말이기도 하니 너무 그러지 말길 바란다.

아무튼 조금 더 생각해 보고 아래에서 답을 확인하도록 하자.


위에서 힌트로 반환형과 반환값을 제시하였다.

반환형은 'int&'이고 반환값은 'num'이다.

따라서 위의 함수에서의 지역 변수 'num'은 저장된 값을 반환하지 않고,

'num'을 참조의 형태로 반환하고 있는 것이다.

그러므로 다음의 코드로 함수를 호출하게 되면

int& ref = RetRefFunc(10);

 

지역 변수 'num'에 'ref'라는 참조자가 하나 더 생성되는 상황이 발생한다.

'필자양반, 그냥 참조자가 하나 더 생기는 거잖수. 이왜안?'(이게 왜 안됨?)

그림 28 - 답답해 죽는 패트

극락에서 원효 대사가 텀블러 컬렉션 하나 늘었다고

탭댄스를 추며 반야심경을 외는 소리가 여기까지 들리는 것 같다.

우린 조금 더 깊이 생각해 볼 필요가 있다.

 

함수가 반환 되면 참조의 형태로 반환된 'num'은 변수 효력 지역을 이탈하여

애니메이션의 비련의 여주인공마냥 먼지가 되어 소멸된다.

그렇게 되면 참조자 'ref'는 소멸된 'num'를 어떻게 참조할 수 있겠는가?

그리고 이후의 코드는 어떻게 되겠는가?

사실 나도 모른다.

그림 29 - 어이를 거하게 털린 독자

하지만 정확한 것은 프로그래머가 원하는 결과가 출력될 가능성은 절대적으로 낮다.

요약하자면, 지역 변수를 참조형으로 반환하는 실수를 유의해야 한다는 것이다.

 

마치며

요즘 영 공부할 맛이 안 난다.

계속 집에만 있어서 그런 것이 확실하다.

공간은 분할이 가장 중요하다고 생각하는 만큼이나

뭔가 하고자 했을 때 능률이 떨어지는 것 같다.

빨리 이 시국이 종식되었으면 하는 바람이다.


참고 및 출처

윤성우의 열혈 C++ 프로그래밍