[ 개발 잡소리 ] 참조는 무엇인가

2024. 3. 19. 10:54개발잡소리

C언어나 C++ 등 포인터와 같은 참조를 처음 접할 때

전두엽과 측두엽이 지끈거리는 것을 온몸으로 느낄 수 있다

 

참조가 뭐길래? 참조는 무엇인가

참조는 원본이 존재하고 다른 변수나 파일에서

그것을 '참조' 원본의 주소를 가지고 있거나 참조자를 통해

원본으로부터 값을 공유받는 것

 

무슨 말인지 하나도 모르겠다

 

참조를 비유한다면 비유할 대상은 많다

예시를 하나 들어보자


만약 조별과제를 팀을 짜서 하고 있다고 치자

 

A, B가 한 팀인데

A가 보고서를 작성하고, B가 자료를 수집한다

 

각각의 대상이 자료를 만드는데

 

1.  B는 A에게 수집한 자료 문서 사본을 넘겨준다

 

2.  A는 구글 문서에 보고서를 작성하여 링크를 B에게 주었다

 

두 경우의 차이가 느껴지는가?

두 가지의 차이는 동기화에서 온다

 

1번의 경우

C가 문서를 추가로 수정할 경우 C에는 변경사항이 적용되지만

B가 가진 문서에는 변경사항이 적용되지 않는다

 

반면 2번의 경우

구글 문서에서 A가 보고서를 작성하면

B가 가진 자료에서도 변경사항이 적용되어 있다

포인터의 주소 참조가 이런 느낌이다.

코드로 본다면 이러하다

void Pointer() {
	string Bogoseo_A = "보고서이빈다";
	string* B = &Bogoseo_A; // 원본의 주소를 할당

	Bogoseo_A = "보고서입니다"; // 원본의 오타를 수정했다
	cout << *B; // 역참조를 통해 값을 가져오기
	
}

분명 원본만 수정했으나

B가 가진 보고서에도 오타가 수정되어 있는 모습을 볼 수 있다 

 

 

하지만 변경되면 안 되거나 동기화를 바라지 않는다면 사본을 만들어 주는 것이 맞다.

 

 


참조자를 통한 참조는 무엇일까

변수를 부르는 또 다른 이름, 즉 별명을 생각한다면 편하다

 

본래 ' 김밍수'라는 이름을 가진 친구가 하나 있다

그리고 이 친구는 ' 밍밍 '이라는 별명을 가지고 있다

 

따라서 이 친구를 부를 때는 밍수라고 부를 수도 있고

밍밍이라고 부를 수도 있다

 

코드로 본다면 이런 느낌이다

void Reference() {
	string name = "김밍수";
	string &mingming = name; // & 참조자를 통해 사용가능

	name = "김밍수 바보";
	cout << mingming;

}

따라서 김밍수를 호출하고 싶을 때

name으로 불러도 되고 mingming이라는 별명으로 불러도 된다는 것이다


포인터와 참조자는 무엇이 다를까?

포인터와 다르게 참조자는 선언과 동시에 참조할 대상을 초기화해주어야 하며

한번 초기화하면 다른 변수를 참조할 수 없게 된다

따라서 포인터보다 조금 더 안전하다

 

그리고 특이하게도 원본 변수 그 자체가 되어 그냥 별명으로써 부르기 때문에

메모리상에 존재하지 않을 수 있다

 


그렇다면 이 참조는 왜 쓰는 걸까?

 

우선 값으로 호출할 때 보다 주소로 복사하는 게 훨씬 싸게 먹힌다

이게 뭔소리냐면 극단적인 비유를 들어보면 쉽게 이해된다

 

만약 ㄹㅇ 어마어마하게 큰 객체를 만들어 놨는데 이 객체를 여러 군데에서 사용하게 될 때.

\

이 객체를 매번 복사해서 사용한다면 메모리가 죽어나갈 것이다.

하지만 이 객체를 찾는 주소만 달랑 저장해서 매번 찾아주기만 한다면?

복사할 때 드는 비용을 크게 줄일 수 있다