int a(int &a, int &b){
내용
}

int b(int *a, int *b){
내용
}

int a,b;
a(a,b);
b(&a,&b);

각 함수 내용은 같다고 할 때(포인터 관련 문법차이 제외)

컴파일되고나서 a랑 b함수 부분이 같다고 생각함? 둘다 일단 포인터를 사용하는건 맞음

하지만 a함수 쪽은 주소 변수를 받을 필요조차 없음. 컴파일 시간때 a함수쪽 인자는 바뀔 일이 없기때문에 실제로 컴파일 되고나면 함수의 인자는 상수처리 되고 어셈블리 레벨에서 보면 실제로 함수쪽에서의 사용을 위해 스택이나 레지스터로 주소변수를 넘기지않고 로더가 결정한 상수값이 바로 명령어에 들어가게됨(정적변수들 처럼)
처리할 코드가 더 적고 자원도 적게 소모하는거지, 주소를 참조하는 건 똑같지만.

그에 반해 포인터쪽은 일단 포인터를 한번 참조해서 진짜 값의 위치를 알아야하는 일종의 동적 과정이기때문에 로더가 결정 지을수 없기에 포인터 값을 가져오고 그 주소(동적)로 가는 과정이 추가됨
게다가 문법상으로 call by value처럼 포인터 값을 지역 스택 이나 레지스터로 받아야 하니 또 자원과 여기에 로드하는 비용이 추가되지(이건 뭐 컴파일러 설계에 따라 달라질 수 있음 최적화문제도 있고)
(내가 C++에서 포인터를 call by reference로 부를 수 있는지는 모르겠음. 안될 이유는 없음(포인터 자체는 정적변수니 로더가 정적주소를 로딩 타임에 결정할 수 있음), 뭐 된다면 int* &a? 로 할려나 모르겠다)

(참고로 보통 c에서 인자는 지역스택으로 받지만 이건 펑션콜 방식에 따라 다름)