int pointer(int* p)
{
return *p;
}
int reference(int& ref)
{
return ref;
}
void func()
{
int num = 3;
num = pointer(&num);
num = reference(num);
}
위 코드에서 p 포인터 변수는 num의 주소 값을 갖고 있고, ref 변수는 num과 정확히 같은 변수를 뜻한다.
내부적으로 어떤 차이가 있는지 disassembly 해보았다.
pointer(int*):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
pop rbp
ret
reference(int&):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
pop rbp
ret
func():
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 3
lea rax, [rbp-4]
mov rdi, rax
call pointer(int*)
mov DWORD PTR [rbp-4], eax
lea rax, [rbp-4]
mov rdi, rax
call reference(int&)
mov DWORD PTR [rbp-4], eax
nop
leave
ret
결론은 둘의 내부적인 처리는 완전히 같다는 것이다.
모두 주소 값을 전달하고 함수 내에서 역참조를 통해 값에 접근한다.
그렇다면 레퍼런스가 나온 이유는 뭘까?
잘못된 포인터 사용의 방지(Segmentation fault, Null reference 등)
포인터를 사용해야 할 때
- 전달받은 주소 이외의 값에 접근해야 할 때(배열의 다음 원소 등)
레퍼런스를 사용해야 할 때
- 전달받은 레퍼런스 변수만을 사용하고 다른 주소를 가리켜야 할 필요가 없을 때