본문 바로가기

프로그래밍/C++

[C++] 이명제조기, 참조자 - 1

들어가기 전에

반갑다.

여러분들은 프로그래머의 길을 걷고 있지 않은가?

컴퓨터를 다루는 모든 IT관련 직종의 필수 기본 소양 패시브가 있다.

Passive - 항시 저장

본인은 이 글을 한 번 날린 전적이 있다.

 

들어가며

참조자(Reference).

프로그래밍을 공부하려는 사람이면 어디선가 많이 들어본 키워드다.

이름만 들어서는 어디다 써먹을지, 무슨 개념인지 감이 잘 오지 않는다.

오늘은 이 녀석이 뭐하는 놈인지를 함께 알아보는 시간을 갖도록 하겠다.

오늘 공부할 '참조자'라는 녀석은 성격상 '포인터'와 비교되기 쉬운데,

참조자는 포인터를 모르더라도 이해할 수 있는 개념이다.

따라서 굳이 포인터의 개념을 끌어와다가 이해하겠답시고 자신을 괴롭히지 않았으면 한다.

그런데 사실은 참조자도 내부적으로는 포인터로 변환되어 동작하기 때문에, 사실상 포인터와 동일한 기능이다.

 

참조자의 이해

변수란 무엇인가. 무엇을 변수라고 하는가.

'아ㅋㅋ 그거 그냥 데이터 담는 그릇같은 거 아니냐?'

완전히 틀렸다고는 할 수 없다만, 맞다고는 할 수 없는 답변이다.

정확하게는 '정적으로 할당된 메모리 공간' 이라고 한다.

그리고 그 이름을 통해서 해당 메모리 공간에 접근도 할 수 있다.

'갑자기 웬 변수 타령이야······. 그래서 참조자가 뭔데;;'

라고 생각하는 사람이 많을 것이다.

뭐 적당히 눈치 챘겠지만 참조자는 변수와 밀접한 관계가 있기 때문에 한 번 짚고 넘어가는 것이다.


우리가 느와르 영화나 웹툰 등을 볼 때마다 등장인물들이 본명 말고

다른 이름 으로 서로를 칭하는 상황을 쉽게 볼 수 있지 않은가?

가령 '흑곰파, 불곰 박문형' 이라거나 '백사파, 살모사 김사혁' 같은,

혹은 '충무공 이순신'이나 '다산 정약용'같은 호도 비슷한 맥락이다.

이러한 것들 모두 본명이 아닌 '이명'이지 않은가?

 

그래서 우리는 아주아주 쓸데없고 난데없이 이런 생각을 해보도록하자

'할당된 메모리 공간(변수)에도 둘 이상의 이름을 부여할 수는 없나?'

솔직히 말해서 '굳이?'라고 생각할 수도 있다.

하지만 우린 참조자에 대해서 공부하는 입장이니 일단 의문을 가져보도록하자.

아무튼 의문을 가져보도록 하자.

왜냐하면 이 질문이 참조자의 본질과도 밀접한 관련이 있기 때문이다.


우선 다음과 같은 코드를

int num1 = 1;

 

실행시키고 굳이 도식화하면 다음과 같다

그림 1 - 변수의 선언

정적으로 메모리 공간을 할당하고, 그 공간의 이름을 'num1'으로 명명,

그 메모리에 1이라는 데이터를 저장한 상황이다.

그리고 다음과 같은 코드를

int& num2 = num1;

 

실행시키고 또 굳이 도식화 해본다면 다음과 같다.

그림 2 - 참조자 선언

이때의 'num2''num1에 대한 참조자'라고 한다

'또, 또, 또, 또, 또 혼자 급발진 하죠? 그래서 이게 뭔데!'

자, 코드와 그림 1, 2를 자세히 살펴보도록 하라.

'num1'이라는 메모리 공간에 'num2'라는 이름이 하나 더 추가되었지 않은가?

또 다른 이름, 변수의 '이명'을 '참조자'라고 한다.


'아니 잠깐만 필자양반, &(Asterisk)가 왜 여기서 나와?'

현재의 우리에게는 충분히 오해의 소지가 있는 코드이긴 하다.

우리가 아는 & 연산자는 변수의 주솟값을 반환하는 연산자이기 때문이다.

예를 들어 유리병은 주로 유체를 담는 용기의 역할도 하지만

상황에 따라서 둔기로도 활용되지 않는가? 법률 제13718호 폭력행위 등 처벌에 관한 법률 「형법」 제2조(폭행 등)

비슷한 맥락으로 & 또한 다양하게 활용되는 것 뿐이다.

그림 3 - &(Asterisk)의 쓰임

그림 3의 첫 번째 코드에서처럼, 이미 선언된 변수 앞에서 사용하면 주솟값의 반환을 명령하는 '연산자'이지만

두 번째 코드에서의 &는 주소 연산자가 아닌 타입을 식별하기 위해 '식별자'로 사용된 것이다.

비슷한 맥락으로, 포인터에서 'int *''int 형 변수에 대한 포인터 자료형'이라고 하는 것 처럼

즉, 'int&''int형 변수에 대한 참조자 자료형' 쯤을 의미한다.

이렇게 선언된 참조자는 대상 변수와 같은 메모리 위치를 참조하게 된다.


'아아······, 그렇다면 「참조자」도 「변수」라는 것인가······.'

사실상 변수로 봐도 무리는 없다.

그 기능과 연산의 결과가 변수와 동일하기 때문이다.

하지만 C++에서는 참조자는 다른 언어와 조금 다르기 때문에 변수와 구분하여 이야기하고 있다.

만드는 순간에만 참조할 변수를 선택할 수 있고 한번 만들어진 참조는 변경할 수 없다.

왜냐하면 다른 언어는 포인터를 참조가 완전히 대체하지만 C++은 그렇지 않기 때문이다.


아무튼 배운 개념을 간단하게 써먹어보기 위해 다음 문장을

num2 = 2;

 

실행시키고 도식화해보면 다음과 같은 구조를 가진다.

그림 4 - 참조자를 이용한 메모리 공간 접근

참조자를 이용하여 num1의 메모리 공간에 접근하여 내부 데이터 값을 변경하였다.

이어서 다음의 두 문장을 실행하면

cout << num1 << endl;
cout << num2 << endl;

 

2라는 값이 두 번 출력되는 것을 확인할 수 있다.

이렇듯 '참조자''자신이 참조하는 변수를 대신할 수 있는 이명'인 것이다.

그럼 다음 예제를 통해서 지금까지 설명한 내용을 직접 확인해 보도록 하라.

#include <iostream>

using namespace std;

int main()
{
    int num1 = 10;
    int& num2 = num1;

    num2 = 20;
    cout << "VAL: " << num1 << endl;   // 동일한 값
    cout << "REF: " << num2 << endl;   // 출력

    cout << "VAL: " << &num1 << endl;  // 동일한 주솟값
    cout << "REF: " << &num2 << endl;  // 접근

    return 0;
}

 

변수와 참조자의 차이는 선언 방식을 제외하고는 거의 없다시피 봐도 무방하다.

일단 선언되고 나면 변수와 큰 차이가 없다.

참조자도 지역적(Local)으로 선언되었다면, 해당 지역을 빠져나가면 소멸된다.

 

마치며

긴말 하지 않겠다.

컴퓨터로 중요한 작업을 할 일이 생긴다면

진짜 미리미리 백업과 저장을 생활화 하자

누군가가 '으아아악!!'하고 처절하게 소리지르고

그제야 'ctrl+s'를 누르는 것도 나쁘지 않지만

그 비명의 주인이 내가 될 수도,

그 비명이 마지막 단말마가 될 수도 있으니까 말이다.

절.대.저.장.해