0. 미리 알아두기
- 참조자로 선언된 변수를 새로운 변수로 보지 말고, 참조하는 그 대상 자체로 보는 것이 편하다.
- 참조자 자체는 별도의 자료형이 아니라, 특정 변수에 접근하는 또 다른 이름(별칭)일 뿐이다.
1. 참조자란?
- 변수의 별칭(alias)으로, 원본 변수와 동일한 메모리 주소를 공유한다.
- 선언과 동시에 반드시 초기화해야 하며, 다른 대상을 참조로 바꿀 수 없다.
- 별도의 메모리 공간을 갖지 않으며, 컴파일러가 내부적으로 원본 변수로 치환하거나 포인터처럼 처리한다.
int num = 5;
int &ref = num;
ref = 3;
2. 참조자와 포인터의 차이
| 구분 | 참조자 | 포인터 |
|---|
| 초기화 | 반드시 필요 | 선택적(null 가능) |
| 재할당 | 불가능 | 가능 |
| NULL | 불가 | 가능 |
| 문법 | 변수처럼 사용 | *, & 연산 필요 |
| 안전성 | 높음 | 낮음(실수 가능) |
3. 참조자의 메모리 동작
- 일반적으로 참조자는 별도의 메모리 공간을 차지하지 않는다.
- 함수 매개변수로 사용될 때 등, 컴파일러 구현에 따라 임시 공간이 할당될 수도 있다.
4. const와 참조자
- const 참조자는 값을 변경할 수 없게 하여 원본 보호에 사용한다.
const int& ref = num;
5. 함수에서의 참조자 활용
-
함수 인자나 반환값에 사용하면 원본을 직접 수정하거나 복사 비용을 줄일 수 있다.
void func(int& x);
int& func_0(int& x) {
return x;
};
int func_1(int& x) {
return x;
};
-
반환값을 참조자로 받으면 원본과 연결, 값으로 받으면 복사본이 된다.
6. 참조자 사용이 적합한 경우
- 함수 인자/반환값에서 원본을 수정하거나 복사 비용을 줄이고 싶을 때
- 항상 유효한 대상을 가리켜야 할 때
- 객체지향 프로그래밍에서 복사 생성자, 연산자 오버로딩 등
7. 포인터가 필요한 경우
- NULL(없음) 상태를 표현해야 할 때
- 가리키는 대상을 바꿔야 할 때
- 동적 메모리 할당, 자료구조(리스트, 트리 등) 구현 시
8. 주의사항
- 참조자는 Dangling Reference(소멸된 변수 참조)에 주의해야 한다.
- 임시 객체를 참조할 때는 const 참조자를 사용해야 한다.
결론
- 참조자는 안전하고 간결한 별칭으로, 함수 인자/반환, 객체지향 프로그래밍에서 적극 활용.
- 포인터는 NULL 가능, 동적 메모리, 자료구조 등 특수한 상황에서 사용.
- 기본적으로 참조자를 우선 사용하고, 필요할 때만 포인터를 쓴다.