본문 바로가기

💻 내 소개 안녕하세요 엄청짱 프로그래머 손다빈 입니다.
  • 나이 : 96년생
  • 특이사항 : MZ세대, INFJ, 오른손잡이, 아이폰 유저
  • 좋아하는 음식 : 햄버거피자치킨솥뚜껑삼겹살떡볶이오튀김밥
  • 취미 : 개발, Programming, 코딩, 프로그래밍, Coding

🥷기술
Unity
Godot
Cpp
Javascript
D3
Vue

🐱 우리집 고양이 소개
츄르 먹은 후 츄르 먹기 전
  • 이름 : 콜라
  • 나이 : 8살
  • 종 : Nado moreum

📱 개인 프로젝트
🏢 참여한 프로젝트
빌런즈 Life is Pair 도씨어부키우기 직장상사혼내주기 서바이벌빙고 SlitherCoin

🌱 내 잔디밭

참조가 참 조으다 본문

글 묶음/지옥에서 온 C++

참조가 참 조으다

초긍정 개발자 다빈맨 2019. 2. 28. 06:00

| C++은 참조(Reference)가 왜 필요했을까



C++에서 참조를 사용해야하는 상황이 오면 항상 같이 떠오르는 대안이 포인터입니다. 도대체 포인터가 있는데 참조를 사용해야 하는 이유가 무엇일까요? 사실 포인터는 상당히 위험한 녀석입니다.

int num=3;
int* ptr = &num
*(ptr+125) = 8; // 옛날엔 예측할 수 없는 무서운 결과를..

참조와 달리 포인터는 증감연산을 이용해서 메모리의 위치를 바꿔서 접근할 수 있습니다. 지금은 예전보다 컴파일러가 똑똑해졌기에 상상하기 힘들지만 예전에는 포인터를 사용해 잘못된 메모리를 참조하는경우, 농담반 진담반으로 컴퓨터의 하드웨어를 손상시킬 수 있다고 할 정도였다니깐 말이죠. 이렇듯 참조의 탄생배경은 C언어의 포인터를 잘못사용하는 최소한의 위험을 없애기 위해서 였습니다.


사실 이런 탄생배경 외에도 예전에 제가 썼던 글 중에 배열과 포인터는 다릅니다 에서 다룬 배열이나 함수를 포인터에 담을 때 포인터로의 부식(Decay)되면서 생기는 단점을 보완하기 위해서도 사용됩니다. 외에도 대부분의 상황에서 참조는 항상 포인터보다 좋습니다.




| 그래도 가끔은 쓸모있는 포인터


아무래도 단점을 보완하기 위해 만들어졌다보니 무조건 참조를 쓰는게 맞습니다. 하지만 포인터를 완전히 배척하기에는 어쩔 수 없는 경우라는게 있습니다. 참조는 주소를 담는게 아닌, 변수 자체에 공간만 공유하고 이름만 하나 더 부여하는 방식이라 NULL을 할당할 수 없습니다. 이렇다보니 값에 NULL이 할당되어야 하는 껀덕지가 보인다면 포인터를 사용해야 합니다.


조금 다른 이야기지만 한가지만 더 재밌는 활용방법이 있습니다.

void Sum(int lv, int rv, out int result)
{
    result = lv + rv;
}

위 코드는 C# 문법으로 작성된 함수입니다. C# 에는 out 이라는 키워드가 있는데요. 이 키워드는 독특하게도 call-by-pass로 전달받은 값을 반드시 변경하도록 강제할 수 있습니다. result 로 전달 받은 매개변수를 참조로 받고 해당 값이 함수 안에서 변경될 것이라는 걸 강제하는 것이죠. 이 놈은 C++에서 포인터나 레퍼런스로 구현할 수 있지만 함수 안에서 이 매개변수가 변경되어야 함을 강제할 순 없습니다. 이때 대안으로 포인터를 이용하는 겁니다.

void Sum(int lv, int rv, int* result){
    *result = lv + rv;
}

기본적으로 항상 매개변수로 포인터 대신 참조를 사용하고, 위와 같이 함수 안에서 이 값이 변경되었음을 의미하는 목적으로 포인터를 사용하는 방법이죠.  (실제로 강제할 순 없지만, 의미론적으로 사용할 수 있습니다.)