[C++] 포인터(Pointer)와 레퍼런스(Reference)
2021. 5. 21. 03:52
안녕하세요. 라이트코드(Light Code) 입니다.
지난 시간에는 C와 C++의 차이를 간략하게 설명해드렸습니다. 이번에는 C++에서도 가장 중요한 개념인 포인터와 비슷한 개념이지만 전혀 다른 특징을 가지고 있는 레퍼런스 개념을 비교분석해서 알려드리겠습니다.
<포인터? 레퍼런스? 그게 뭐지?>
C++를 공부하다보면 레퍼런스(Reference) 또는 참조라 라는 새로운 개념을 배우게 됩니다.
어떻게 보면 C언어를 공부할 때에 굉장히 어렵게 만들었던 포인터(Pointer)와 유사해 보이는데 어떠한 대상을 가리킨다는 점에서는 같다고 볼 수 있습니다.
하지만 포인터와 레퍼런스는 차이점이 있습니다.
그 중에 여러분이 C++을 할 때 반드시 알아야 할 두 가지 중요한 차이점을 알려드리겠습니다.
1. NULL값의 허용 여부
포인터는 NULL 값을 허용하지만 레퍼런스는 NULL값이 될 수가 없습니다.
포인터를 사용할 때에 ‘Null pointer exception’ 또는 ‘Segmentation Fault’ 에러들의 원인은 포인터를 초기화하지 않거나 NULL 값을 가리키고 있는 포인터에 접근했을 때 발생했습니다.
struct person
{
int birthday;
};
struct person *choi = NULL;
choi->birthday = 0101;
위의 코드를 보게 되면 NULL 포인터를 참조 하고 있는 choi의 변수를 접근 할 때 에러가 발생하게 됩니다.
즉 포인터 변수를 사용할 때에는 반드시 아래와 같이 validation 하는 처리를 해줘야 이러한 에러들을 방지할 수 있습니다.
if (choi)
choi->birthday = 0101;
else
printf("choi : null\n");
하지만 포인터를 사용하지 않고 레퍼런스를 사용하게 되면 이러한 문제는 발생하지 않습니다.
레퍼런스는 NULL 값을 할당할 수 없도록 제한되어 있기 때문입니다.
포인터와 목적은 같지만 잘못된 참조로 인해 발생되는 오류를 방지하기 위해 고안되었다고 이해하기가 편합니다.
이러한 특성은 함수 매개변수(Function parameter)에 사용할 때에도 동일하게 적용이 됩니다.
void pointer(struct person*);
void reference(struct person&);
위의 코드처럼 선언된 함수를 사용 할 때에는 포인터 매개변수를 갖는 함수는 매개변수에 접근할 때 반드시 NULL값 여부를 체크해야 합니다. 반면 레퍼런스 매개변수를 갖는 함수는 NULL값에 대한 여부를 허용하지 않기 때문에 생략이 가능합니다.
어느 프로그래밍 언어를 사용할 경우 매개변수가 NULL을 허용하는지 여부는 프로그램을 설계할 때 매우 중요한 부분입니다.
이 실수로 인해 함수의 설계사상이 복잡해질 수 있습니다.
앞으로 함수를 설계할 때 이러한 차이를 반드시 이해하는 것이 매우 중요합니다.
2. 참조 대상 할당 및 접근
포인터는 할당 할 때 참조 대상에 대해 & 연산을 통해 주소값을 할당하는데 레퍼런스에는 참조 대상을 그대로 할당합니다.
struct person choi;
int a = 1;
int *p = &a; // 포인터는 주소값을 할당
int &r = a; // 레퍼런스는 직접 할당
pointer(&choi); // 주소값 입력
reference(choi); // 직접 입력
즉 레퍼런스 변수는 NULL값을 할당 할 수가 없으며 선언과 동시에 초기화를 하지 않으면 컴파일 오류가 발생합니다.
이러한 차이는 함수 호출 시에도 같이 적용되는데 함수를 통해 넘겨받은 참조를 사용할 때에도 포인터는 *, -> 등의 포인터 연산자를 통해 접근해야 하지만 레퍼런스는 지역변수처럼 접근이 가능합니다.
단, 레퍼런스의 값을 변경하게 된다면 레퍼런스가 참조하고 있는 실제 변수의 값이 변경됩니다
<포인터와 레퍼런스는 이거구나!>
레퍼런스는 포인터의 잘못된 사용으로 인해 생기는 수많은 문제들을 최소화하기 위해 등장했다고 이해하면 됩니다. 무한한 가능성을 열어둔 포인터와 달리 레퍼런스는 위에서 살펴본 것과 같이 여러가지 주의사항이 존재합니다.
이러한 주의사항에도 Call by reference로 활용하는 데에는 문제가 되지 않기 때문에 보다 안정성이 있는 프로그램을 위해 적극적으로 활용하는 것을 추천해드리겠습니다.