프로그래밍/C,C++

[C++] 반환값 최적화(RVO, NRVO)

GONII 2025. 5. 14. 18:34

 

📦 개념 요약

용어 의미
RVO (Return Value Optimization) 임시 객체를 직접 호출자 영역에 생성하여 복사/이동 생략
NRVO (Named Return Value Optimization) 이름 있는 지역 변수를 반환할 때도 복사/이동 없이 직접 생성

✅ RVO (Return Value Optimization)

예제:

Test createTest() {
    return Test();  // 임시 객체 반환
}
  • Test() 생성 시, 컴파일러가 호출자 스택에 직접 객체 생성
  • 그래서 생성자 1번만 호출, 복사/이동 생략됨

➡️ 객체를 “리턴용 임시 공간”에 직접 생성하는 방식


✅ NRVO (Named Return Value Optimization)

예제:

Test createTest() {
    Test t;
    return t;  // 이름 있는 변수 반환
}
  • t는 함수 내부 지역 변수지만
  • 컴파일러가 t를 호출자 스택에 직접 생성해서 복사/이동 생략 가능

➡️ 단, 조건문 등 분기가 있으면 NRVO가 적용되지 않을 수 있음


🔥 실제 실행 순서 비교

struct Test {
    Test() { std::cout << "Constructor\n"; }
    Test(const Test&) { std::cout << "Copy\n"; }
    Test(Test&&) { std::cout << "Move\n"; }
};

Test make() {
    return Test(); // RVO
}

int main() {
    Test t = make(); // 생성자만 출력될 수도 있음 (RVO)
}
  • 출력 결과:
    • C++17 이전: Move or Copy
    • C++17 이후: Constructor만 (복사/이동 생략됨 — RVO guaranteed)

🚀 C++17 이후 변경점

C++17부터 RVO는 강제됨 (mandatory copy elision)

Test f() {
    return Test();  // RVO 반드시 적용됨
}
  • 복사 생성자/이동 생성자가 삭제되어 있어도 컴파일됨 → 객체는 복사 없이 생성됨

⚠️ 주의할 점

상황  RVO/NRVO 적용 여부
return Test(); ✅ RVO
Test t; return t; ✅ NRVO (C++17 이전에는 optional)
if (...) return t1; else return t2; ❌ NRVO 불가
return std::move(t); ❌ NRVO 못 함 → 강제로 이동 발생

❌ 예시 (NRVO 안 됨):

Test create() {
    Test t;
    return std::move(t); // 이동 발생 → NRVO 적용 안 됨!
}

📌 정리

구분 설명
RVO 임시 객체 직접 리턴 시, 복사/이동 없이 생성됨
NRVO 이름 있는 객체도 복사 없이 리턴 가능 (조건 있음)
C++17 RVO는 강제 적용, NRVO는 여전히 optional
std::move() 사용 NRVO 못 하게 방해함 (주의!)

✨ 실전 팁

  • 값을 리턴할 때 std::move() 쓰지 마라!
  • return std::move(obj); // ❌ NRVO 방해함 return obj; // ✅ NRVO 가능
  • 생성자/복사/이동자 로그 찍어서 최적화 확인 가능
  • 구조체 반환 비용 때문에 복사비용 걱정하지 않아도 되는 시대임 (C++17+)
반응형

'프로그래밍 > C,C++' 카테고리의 다른 글

[Modern C++] std::call_once  (1) 2025.08.05
[Modern C++20] 🚀주요 특징 & 설명  (0) 2025.04.16
[Modern C++20] coroutine  (0) 2025.04.11
[Modern C++20] concept  (0) 2025.04.08
[Modern C++] string_view  (0) 2025.04.02