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 의미론은 "보장된 복사 생략"으로 이어져 복사가 필요 없게 됐어요.
- 이동·완벽 전달을 이해하려면 값 범주가 필수예요.