C++에서 함수에 값을 전달할 때 포인터(pointer)와 참조(reference)는 자주 혼동되는 개념입니다. 두 방식 모두 원본 변수에 접근할 수 있다는 공통점이 있지만, 동작 방식과 사용 규칙에서 중요한 차이가 있습니다. 이 글에서는 포인터와 참조의 기본 문법부터 핵심 차이점까지 자세히 살펴보겠습니다.
포인터(Pointer)란?
포인터 변수는 다른 변수의 메모리 주소를 저장하는 변수입니다. 포인터를 사용하면 해당 주소에 저장된 값에 간접적으로 접근하고 수정할 수 있습니다.
선언 문법
Type *pointer;
초기화
Type *pointer; pointer = &variable_name;
참조(Reference)란?
매개변수를 참조로 선언하면 기존 변수의 별명(다른 이름)처럼 동작합니다. 참조는 새로운 대상을 가리키는 것이 아니라 이미 존재하는 변수를 그대로 가리키며, 참조를 통해 값을 읽거나 수정하면 원본 변수에 그대로 반영됩니다.
선언 문법
Type &newname = existing_name;
초기화
Type &ref = variable_name;
포인터와 참조의 주요 차이점
역할의 차이: 참조는 기존 변수를 다른 이름으로 부르는 별명 역할을 하고, 포인터는 변수의 메모리 주소를 저장합니다.
null 값 허용 여부: 참조에는 null 값을 할당할 수 없지만, 포인터는 null 값을 가질 수 있습니다.
전달 방식: 참조 변수는 값에 의한 전달(pass by value)처럼 자연스럽게 사용할 수 있으며, 포인터는 참조에 의한 전달(pass by reference) 방식으로 주소를 명시적으로 전달해야 합니다.
초기화 필수 여부: 참조는 선언과 동시에 반드시 초기화해야 하지만, 포인터는 선언만 해두고 나중에 초기화할 수도 있습니다.
메모리 구조: 참조는 원본 변수와 같은 메모리 주소를 공유하며 스택에 약간의 공간을 추가로 차지할 수 있고, 포인터는 스택에서 자신만의 독립적인 메모리 주소와 크기를 가집니다.
한눈에 비교하기
| 구분 | 포인터 | 참조 |
|---|---|---|
| 저장 내용 | 변수의 메모리 주소 | 변수의 별명 |
| null 할당 | 가능 | 불가능 |
| 초기화 시점 | 선언 후 나중에 가능 | 선언 시 필수 |
| 대상 재지정 | 가능 | 불가능 |
| 메모리 주소 | 자체 주소 보유 | 원본 변수와 주소 공유 |
마무리
정리하면, 포인터는 유연성이 높지만 null 검사 등 주의해야 할 부분이 많고, 참조는 안전하고 직관적이지만 한 번 지정된 대상을 변경할 수 없습니다. 따라서 대상 변수가 반드시 존재하고 고정되어 있는 경우에는 참조를, 대상이 없을 수 있거나 실행 중에 바뀌어야 하는 경우에는 포인터를 사용하는 것이 좋은 코딩 습관입니다.