value_category — 값 범주

value_category — 값 범주 (Value categories)

**값 범주(value category)**는 표현식이 객체를 나타내는지, 값을 나타내는지, 그리고 그 객체가 임시인지 등을 분류하는 개념이에요. lvalue, prvalue, xvalue로 나뉘어요 (C++17 기준).

값 범주는 과부하 해석(복사 vs 이동), 참조 바인딩 등에 결정적인 영향을 줘요. C++11 이동 의미론을 이해하는 핵심 기반이에요.

출처: cppreference

본문

C++ 표현식은 값 범주로 분류돼요. 핵심 범주는 lvalue, prvalue, xvalue이고, 이들을 합쳐 glvalue(rvalue 포함)로 부르기도 해요.

lvalue

  • 이름이 있는 객체나 함수를 나타내는 표현식
  • 주소를 가질 수 있고, 수명이 있는 객체를 가리켜요
  • 예: 변수 이름 x, 배열 요소 a[i], 멤버 obj.m, *ptr
int x = 5;
x       // lvalue
a[2]    // lvalue

prvalue (pure rvalue)

  • 임시 값을 계산하는 표현식. 주소가 없는 순수한 값
  • 예: 리터럴 42, 1 + 2, 함수 호출 결과(값 반환), std::unique_ptr
42          // prvalue
x + 1       // prvalue (계산 결과)

xvalue (expiring value)

  • 수명이 곧 끝나 이동할 수 있는 임시를 나타내는 rvalue
  • 예: std::move(x), static_cast<T&&>(x), rvalue 참조 반환
std::move(x)   // xvalue

glvalue / rvalue

  • glvalue(generalized lvalue) = lvalue + xvalue (객체나 함수를 나타냄)
  • rvalue = prvalue + xvalue (이동 가능)

왜 중요한가

값 범주는 다음을 결정해요.

  • 과부하 해석 — rvalue엔 이동 생성자가, lvalue엔 복사 생성자가 선택돼요.
  • 참조 바인딩 — lvalue 참조는 lvalue에만, rvalue 참조는 rvalue에만 바인딩.
  • 복사 vs 이동 — prvalue/xvalue는 이동, lvalue는 복사.
void f(int&);    // lvalue
void f(int&&);   // rvalue

int x = 1;
f(x);        // f(int&) 선택
f(std::move(x)); // f(int&&) 선택

요약 다이어그램

        expression
       /          \
    glvalue        rvalue
   /      \       /      \
  lvalue  xvalue prvalue   (xvalue)

노트 (Notes)

  • decltype은 값 범주를 타입에 반영해요 ((x)는 lvalue → int&).
  • C++17의 prvalue 의미론은 "보장된 복사 생략"으로 이어져 복사가 필요 없게 됐어요.
  • 이동·완벽 전달을 이해하려면 값 범주가 필수예요.

더 알아보기 (Learn more)

cppreference