C++ Type Category
glvalue(generalized lvalue)는 일반화된 좌측값
rvalue는 우측값
lvalue는 좌측값
xvalue(eXpiring value)는 소멸하는 값
prvalue(pure rvalue)는 순수 우측값
C++에서 타입 카테고리를 따질 때 크게 두 가지로 구분 합니다.
- Identity(정체를 알 수 있는가?)
- Movable(이동 시킬 수 있는가?)
모든 타입은 다음과 같이 다섯 가지고 구분 할 수 있어요.
lvalue
Identity && Not Movable
즉, 정체를 알 수 있고 이동 시킬 수 없습니다.
int n;
int m;
n과 m은 정체를 알 수 있나요? n와 m은 다른 주소를 가지고 있고 이 주소값들에 의해서 구분 됩니다.
즉, 정체를 알 수 있습니다.
그렇다면 이동은 가능한가요?
int n = 1;
int&& x = n;
이 코드는 컴파일 오류가 발생합니다. &&는 rvalue reference입니다.
즉, 이동 시킬 수 없습니다.
lvalue는 접근할 수 있는 주소를 가진 변수입니다. 이동 연산을 할 수 없습니다.(형 변환을 하면 가능)
- 이름이 있는 변수, 함수
int n
&foo() - 전위 증감 연산자
++a, --b - 배열 참조식
a[n] - 복합 대입 연산식들
a = b, a += b, a *= b - 스트링 리터럴
"hello"
[객체 지향 프로그래밍/C++ 프로그래밍] - 문자열 리터럴이 lvalue인 이유
& 연산자를 이용해 주소값을 얻을 수 있어야 합니다.
예를 들어 &++a, &"hello" 모두 올바른 주소를 얻을 수 있습니다.
prvalue(pure rvalue)
Not Identity && Movable
즉, 정체를 알 수 없고 이동 시킬 수 있습니다.
prvalue는 접근 할 수 있는 주소가 없는 표현식입니다. 이동 연산이 가능합니다.
- 후위 증감 연산자
a++, b-- - 스트링 리터럴을 제외한 모든 리터럴
1, true, nullptr - 산술/논리 연산자 식들
a + b, a && b, a < b
& 연산자를 이용해 주소값을 얻을 수 없습니다.
예를 들어 &a++, &true 모두 오류입니다. 그리고 할당 연산에서 좌측에 올 수 없습니다.
xvalue
Identity && Movable
즉, 정체를 알 수 있고 이동 시킬 수 있습니다.
xvalue 표현식의 일반적인 아이디어는 어떠한 오브젝트가 곧 소멸될 예정이므로 이 오브젝트는 move 해줘야 한다는 것을 명시적으로 표현하는 것입니다.
struct X { int n; };
extern X x;
4; // prvalue가 없음
x; // lvalue
x.n; // lvalue
std::move(x); // xvalue
X{4}; // prvalue: identity가 없으므로
X{4}.n; // xvalue: identity가 있고 리소스가 재사용 될 수 있음
lvalue와 prvalue 두 가지만 있다면 좌측 값을 이동 시킬 방법이 없기에 xvalue가 있어야 합니다.
std::move 함수는 우측값 레퍼런스를 리턴합니다.
https://docs.microsoft.com/ko-kr/cpp/cpp/lvalues-and-rvalues-visual-cpp?view=vs-2019
https://docs.microsoft.com/ko-kr/windows/uwp/cpp-and-winrt-apis/cpp-value-categories