C++ 값 카테고리(Value Category)란?
C++11부터 모든 표현식(expression)은 lvalue, xvalue, prvalue라는 세 가지 기본 값 카테고리로 분류됩니다. 여기에 조합 개념인 glvalue와 rvalue를 더해 총 다섯 가지 용어가 사용됩니다. 이 개념은 이동 시맨틱(move semantics)과 완벽 전달(perfect forwarding)을 이해하는 데 필수적이므로, 각각의 정의와 특징을 자세히 살펴보겠습니다.
1. lvalue(좌값)
lvalue는 프로그램이 접근할 수 있는 실제 메모리 주소를 가지는 표현식입니다. 이름이 붙어 있어 여러 문장에서 계속 참조할 수 있다는 것이 특징입니다.
lvalue에 해당하는 표현식의 예는 다음과 같습니다.
- 변수 이름 (const 변수 포함)
- 배열 요소
- lvalue 참조를 반환하는 함수 호출
- 비트 필드(bit-field)
- 공용체(union)
- 클래스 멤버
2. xvalue(만료값)
xvalue(eXpiring value, 만료값)는 직접적인 주소는 없지만, rvalue 참조를 초기화하는 데 사용할 수 있어 해당 참조를 통해 접근 가능한 표현식입니다. 곧 소멸될 자원을 안전하게 '훔쳐올' 수 있다는 의미에서 만료값이라 불립니다.
대표적인 예로는 rvalue 참조를 반환하는 함수 호출(std::move()의 결과 등)이나 특정 형태의 배열 첨자 표현식 등이 있습니다.
3. glvalue(일반화된 좌값)
glvalue("generalized" lvalue, 일반화된 좌값)는 새로운 독립적인 카테고리가 아니라 lvalue 또는 xvalue를 통칭하는 상위 개념입니다. 즉, 위치(identity)를 가지는 모든 표현식이 glvalue에 속합니다.
4. rvalue(우값)
rvalue는 역사적으로 대입 표현식의 오른쪽(right-hand side)에 위치할 수 있었기 때문에 붙은 이름입니다. rvalue는 다음 중 하나에 해당합니다.
- xvalue
- 임시 객체(temporary object) 또는 그 하위 객체(subobject)
- 객체와 연관되지 않은 값
즉, rvalue는 이동(move)될 수 있는 값을 의미하며, C++11의 이동 시맨틱에서 핵심적인 역할을 합니다.
5. prvalue(순수 우값)
prvalue(pure rvalue, 순수 우값)는 프로그램이 접근할 수 있는 주소가 없는 표현식입니다. 임시적인 값으로, 곧바로 사용되거나 다른 객체를 초기화하는 데 쓰입니다.
prvalue의 예는 다음과 같습니다.
- 리터럴 (
42,'a',true등) - 참조가 아닌(non-reference) 타입을 반환하는 함수 호출
전체 관계 정리
다섯 가지 값 카테고리의 관계를 요약하면 다음과 같습니다.
- glvalue = lvalue + xvalue → 위치(identity)를 가지는 표현식
- rvalue = xvalue + prvalue → 이동할 수 있는 표현식
- xvalue는 glvalue이면서 동시에 rvalue에 속하는 교집합
이 분류 체계를 이해하면 std::move, 이동 생성자, rvalue 참조 등 현대 C++의 핵심 기능들이 어떻게 동작하는지 명확하게 파악할 수 있습니다.