본문 바로가기
C++

참조 반환(Return by Reference)의 이해와 활용

by Oz Driver 2026. 1. 27.

C++ 에서 함수 리턴 시 발생하는 복사 비용을 줄이고, 원본 데이터를 효율적으로 제어하는 원리에 대해 정리합니다.

 

1. 함수 리턴 시 '임시 복사본' 이 생성

함수는 내부에서 return 문을 만나면, 반환할 값을 임시 메모리에 복사하여 생성해 둡니다. 이때 복사 비용이 1번 발생하게 됩니다.

Item GetItem()
{
    return item_; // item_를 복사하여 '임시 객체'를 생성 후 반환
}


여기서 주의할 점은 item_가 클래스의 멤버 변수라 하더라도, 멤버 변수 원본 데이터가 직접 반환되는 것이 아니라 임시 객체를 거쳐서 반환된다는 점입니다. 따라서 이 임시 객체는 해당 문장이 끝나면 소멸하는 존재이므로, 외부에서는 참조 형태로 받을 수 없습니다.

Item& a = GetItem(); // 컴파일 오류

 

이 문장은 컴파일 에러가 발생합니다. 사라질 존재를 참조하는 것은 위험하기 때문에 컴파일러 수준에서 이를 방어하는 것입니다.

 

2. 참조 반환 (Return by Reference) 의 역할

리턴 타입에 &를 붙이는 것은 컴파일러에게 "복사본을 만들지 말고 원본의 주소(참조)를 그대로 넘겨라"고 명령하는 것입니다.

Item& GetItem()
{
    return item_; // 복사 생성자 호출 없이 원본 item_의 참조를 반환
}


이 방식을 사용하면 함수 리턴 단계에서 발생하는 복사 비용이 사라지며, 외부에서 원본 데이터에 직접 접근할 수 있는 상태가 됩니다.

 

3. 참조로 반환하고, 참조로 받기

함수가 참조(&)로 반환할 준비가 되었다면, 이를 받는 쪽에서도 참조로 받아야 데이터의 '원본성'이 유지되고 대입 시 발생하는 추가 복사 비용을 줄일 수 있습니다.

Item& GetItem()
{
    return item_;
}

Item& myItem = GetItem();


이렇게 하면 myItem 은 클래스 멤버 변수인 item_ 그 자체가 됩니다. 다만, 원본을 직접 다루기 때문에 데이터 훼손의 위험이 따릅니다. 이를 방지하기 위해 const를 붙여 수정을 금지하면서도 성능은 유지하는 방식을 주로 사용합니다.

// 원본의 내용은 보호하면서 복사 비용은 발생하지 않음
const Item& myItem = npc.GetItem();


4. 예외 : 참조 없는 반환을 const & 로 받기 (수명 연장)

특이하게도 C++ 컴파일러는 참조가 아닌 '값' 을 반환하는 함수를 const &로 받을 때 예외적인 조항을 적용합니다.

Item GetItem()
{
    return item_; // 값 반환 (복사본 생성)
} 

const Item& myItem = GetItem();


원래 GetItem() 이 반환한 임시 객체(복사본)는 즉시 사라져야 하지만, 받는 쪽에서 const &를 사용하면 컴파일러는 이 임시 객체의 수명을 myItem 변수가 사라질 때까지 연장해 줍니다. 하지만 이 방식은 함수 리턴 시 발생하는 1번의 복사 비용은 피할 수 없으므로, 성능 최적화 관점에서는 3번 방식(양쪽 다 참조)이 더 유리합니다.

 

요약

배달 방식 (Return Type) : 원본을 그대로 보낼 것인지(&), 복사본을 보낼 것인지 결정합니다.

받는 태도 (L-Value) : 보낸 것을 다시 내 메모리에 복사할 것인지, 참조(&)로 공유할 것인지 결정합니다.