금융 경제 보험 정보

C++ 기초개념 - 참조 Reference 무엇인가? 본문

카테고리 없음

C++ 기초개념 - 참조 Reference 무엇인가?

정보캣 2023. 11. 3. 09:11

앞선 글에서 포인터의 개념을 알아보았다. 포인터랑 비슷한데 좀 다르다. 이런 헷갈리는 것들은 결국 개념을 정확히 이해하고 있어야 한다. 개념을 정확히 이해하려면 이 개념을 왜 만들게 되었는지 부터 알아야 한다.

1.문제 : 지역변수는 변수를 그대로 복사해서 다른 함수에서 쓰지 못한다.
결국 가장 최초의 근본적인 문제는 지역변수를 해당 함수 블록내에서만 쓸 수 있으며 다른 블록에서는 쓰지 못한다는 것이다.

이를 해결하기 위한 방법으로 메모리 주소를 활용하는 포인터가 있고 변수를 특정하는 별명을 만드는 참조가 있다

2. 문제가 발생하는 가장 근본적인 원인
그럼 왜 지역변수를 다른 변수로 쓰지 못하는 것인가? 그건 C++ 가 작동하는 가장 근본 디자인 원리를 이해해야 한다.

예를 들어보자. 우리집에는 이지은 이라는 딸이 한명이 있다. 우리 지은이는 노래를 너무나 아름답게 잘 부른다. 이걸 직접 들으면 가장 좋지만, 우리 딸이 남의 집에 가서 노래를 부를 수는 없으니 딸의 노래를 테이프로 녹음해서 보내준다. 우리 지은이는 소중하니까 ....

남의 집에서도 딸의 녹음 테이프를 들어보니까 너무나 잘부른다. 그런데 딱 하나 아쉬운 점이 있다면 박자가 조금 느리다는 것이다. 그래서 테이프를 빨리 감아서 박자를 조금 빠르게 해서 들으니 너무나 좋다.

자 여기서 옆집에서 노래를 빠르게 감았다고 하여, 우리집 딸의 실제 노래가 빠르게 바뀌었나? 아니다. 옆집에 있는 딸의 노래와 우리집에 있는 딸의 노래는, 복사를 해간 것일 뿐 실제와는 사실 별개의 것이기 때문에 옆집에서 박자를 조정했다고 하여 우리 딸의 실제 노래에 영향을 줄 수 없다.

이것이 바로 C++에서 한 함수 블록안의 매개변수를 다른 함수로 보내는 방법이다. 실제 오리지날 변수는 그 블록 안에 유지한체 카피본을 다른 블록 함수로 보낸다. 그렇기 때문에 다른 블록에서 그 카피본을 받아서 함수로 만들어서 다시 해당 블록안에서 사용한다고 한들 각 매개변수는 이미 다른 변수이기 때문에 영향을 주지 못한다.

이는 C++가 딸을 너무나 사랑한 아니, 매개변수의 고유성을 지키기 위한 디자인 구조이다.

3. 코드를 통해서 위의 상황 살펴보기

int main() {
    int x = 10;
    int y = 20;

    swap_by_value(x, y);
    std::cout << x << " " << y << std::endl;  

    swap_by_reference(x, y);
    std::cout << x << " " << y << std::endl; 

    return 0;
}

위의 함수를 보면 지역변수 X와 Y가 있고, 실제 할당된 인수로 10과 20이 있다.
그런데 각 스왑의 방법을 통해서 실제 각 인수를 교환하려고 한다.

void swap_by_value(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
        std::cout << a << " " << b << std::endl;  

}

먼저 위에서 참조를 사용하지 않은 코드를 살펴보자
여기서는 a,b 라는 변수를 복사해 와서 스왑을 실행한다.
여기서 a,b는 실제 해당 하는 인수 그자체를 가져와서 실행하는 것이 아니라 인수를 복사해서 가져왔다 (딸의 노래 카피 테이프)
이 코드를 실행하면 해당 void swap_by_value 블록 안에서는 인수가 교환된다.
결과 값으로 20,10 이 나온다.

여기서 코드가 실행되는 과정을 디버깅한번 해보면 아래 사진처럼 temp:0 , a:10, b:20 으로 각각 복사된 정수가 진행되는 것을 확인할 수 있다.

그리고 마지막 메인의

swap_by_value(x, y);
std::cout << x << " " << y << std::endl;

출력값을 확인 해보면 10,20이 나온다
왜냐하면 변수를 복사만 해 갔기 때문에 메인함수의 진짜 오리지날 인수와는 별개의 존재이기 때문이다.

그래서 메인의 오리지날 변수 a,b는 바뀌지 않는다.

마치 연관되어 있어 보이는 코드이지만 사실은 전혀 관련 없는 두 변수...

4. 참조를 사용해서 문제해결하기

이런 문제를 해결하기 위한 방법으로 참조를 사용한다. 참조는 오리지날 변수 Original Value그 자체를 사용하는 방법인데, 이를 위해서 이름을 하나 더 지칭해서 사용하게 한다. 실존 하는 값 자체를 특정하는 이름을 하나 더 만들어서 실제 오리지날 변수를 수정하게 하는 방법이다.

위의 딸의 노래를 다시 예로 들어보자. 우리딸 지은이가 본캐릭터이라면 부캐로 '아이유'라고 지칭한다. 이름만 다르게 호칭할 뿐이지 지은이 노래 = 아이유 노래는 실제적으로 똑같은 것이다. 이제 아이유가 옆집으로 가서 공연을 한번 해줬다. 옆집에서 피드백을 받아서 노래 박자를 조금 빠르게 수정했다. 그리고 우리집에 와서 노래를 다시 불렀더니 이럴 수가 박자를 딱딱 알맞게 잘 부르네? 왜냐하면 이지은 = 아이유 이니까

이런 원리로 참조는 오리지날 변수를 수정할 수 있는 방법을 제시한다.

참조를 사용하는 방법은 변수의 타입 뒤에 &를 사용해주면 된다.

예를 들어
int a = 10;
int& ref = a;

이렇게 사용 할 수 있다. 이말은 즉 a = 10 = & ref 가 된다.

5. 예시 코드를 이용해서 참조 이해하기

void swap_by_reference(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;

            std::cout << a << " " << b << std::endl; 

}

위의 코드에서 이번에는 레퍼런스, 즉 참조를 이용한 예시를 살펴보자
a, b라는 매개변수를 받지만, 이번에는 참조를 이용하여 원본 변수를 직접 받는다
여기서 코드에 실제로 받는 것을 디버깅 해보면 아래 그림처럼 복사된 변수의 인수 값이 아니라 변수의 실제 메모리 주소가 있는 것을 볼 수 있다.
a: 0x000000016fdfeac8 b: 0x000000016fdfeac4

즉 단순히 변수의 값을 복사한 것이 아니라 실제 변수를 지칭하고 있는 것이며 그로인해 지칭된 주소를 &a, &b 했을 경우 실제 변수 값이 10,과 20이 나온다

그래서 메인 함수의

swap_by_reference(x, y);

std::cout << x << " " << y << std::endl;


출력 결과 역시 20,10 으로 교환되어 있다.

*전체코드

#include <iostream>

void swap_by_value(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
        std::cout << a << " " << b << std::endl; 

}

void swap_by_reference(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;

            std::cout << a << " " << b << std::endl; 
}

int main() {
    int x = 10;
    int y = 20;

    swap_by_value(x, y);
    std::cout << x << " " << y << std::endl;  // This will print "10 20"

    swap_by_reference(x, y);
    std::cout << x << " " << y << std::endl;  // This will print "20 10"

    return 0;
}

 

Comments