값 전달 (Call by Value)

  • 인자를 함수로 넘길 때 값을 복사해서 전달하는 방식입니다.
  • 장점:
    • 함수가 인자를 마음대로 바꿔도 원본에 영향이 없음
    • API가 단순해짐(널/수명 문제 감소)
  • 단점:
    • 구조체/컨테이너가 크면 복사 비용이 커질 수 있음

짧은 규칙:

  • int, float 같은 작은 기본 타입은 값 전달이 자연스럽습니다.
  • 큰 구조체는 “읽기만 한다면” 보통 const&를 먼저 고려합니다.
int Add(int a, int b) { return a + b; }  // 값 전달이 자연스러운 예

포인터 전달 (Call by Pointer)

  • 주소를 복사해서 전달합니다. (원본 데이터를 직접 바꿀 수 있음)
  • 포인터 전달이 특히 좋은 경우:
    • “대상이 없을 수도 있다”를 표현해야 할 때 (nullptr)
    • 함수가 원본을 수정해야 하는데, “참조 문법”을 쓰기 애매한 상황
  • 단점/주의:
    • nullptr일 수 있으므로 널 체크가 필요
    • 잘못된 포인터(댕글링/미초기화)면 크래시/메모리 오염 위험
void Heal(StatInfo* player, int amount)
{
    if (player == nullptr)
        return;

    player->hp += amount;
}

참조 전달 (Call by Reference)

  • void Func(StatInfo& player)처럼 원본을 참조하는 방식입니다.
  • 장점:
    • 복사 없이 원본을 다룰 수 있음
    • 문법이 “값처럼” 보여서 가독성이 좋음 (player.hp처럼 . 사용)
    • 참조는 nullptr를 담을 수 없으므로(“없다” 상태 표현 불가) 의도가 더 명확해짐
  • 주의:
    • 원본을 바꿀 수 있으니, 함수 이름/의도(힐/세팅 등)가 명확해야 합니다.
    • “없을 수도 있다”를 표현해야 하면 참조보다 포인터가 맞습니다.
void HealRef(StatInfo& player, int amount)
{
    player.hp += amount;
}

const 참조

  • const StatInfo&는 “복사 비용 없이, 읽기 전용으로 전달”할 때 가장 자주 쓰는 형태입니다.
  • 장점:
    • 큰 구조체를 복사하지 않고 전달 가능
    • 함수 내부에서 수정이 막혀서 의도가 명확
void PrintPlayer(const StatInfo& player)
{
    std::cout << player.hp << '\n';
}

OUT 매크로

  • OUT은 C++ 문법이 아니라, “이 인자는 함수가 채워주는(out) 용도다”라는 의도 표시용 표기입니다.
  • 컴파일 단계에서는 사라지고, 사람에게만 의미가 있습니다.
#define OUT

void CreateMonster(OUT StatInfo& monster)
{
    monster.hp = 40;
    monster.attack = 8;
    monster.defence = 1;
}

어떤 걸 선택해야 하나? (결정표)

  • 값 전달: 작고(기본 타입), 원본을 안 바꾸는 게 자연스러울 때
  • const 참조: 크고, 읽기 전용으로 넘길 때(가장 흔함)
  • 참조: 원본을 “반드시” 수정해야 할 때(없을 수 없음)
  • 포인터: 원본을 수정할 수도 있는데, “없을 수도 있음(nullptr)”까지 표현해야 할 때

체크 질문 (스스로 답해보기)

  • “없을 수도 있다”를 표현하려면 포인터/참조 중 무엇이 맞을까?
  • 큰 구조체를 읽기만 할 때, 값 전달 대신 const&를 쓰는 이유는?

profile
李家네_공부방

0개의 댓글