Value Category (prvalue / xvalue / lvalue / glvalue / rvalue)

MwG·2025년 11월 19일

C++

목록 보기
13/14

1. lvalue

1-1. 정의

“이름이 있고, 주소를 잡을 수 있고, 계속 존재하는 객체”를 나타내는 표현식

&expr 해서 주소를 얻을 수 있는 애들이 대부분 lvalue

1-2. 예시

int x = 10;
x;          // x  → lvalue
int& r = x; // r  → lvalue (참조도 결국 객체의 또 다른 이름)

struct S { int a; };
S s;
s;          // s  → lvalue
s.a;        // s.a도 lvalue

x, s, s.a 전부 “실제 메모리 어딘가에 있는 객체”

나중에 다시 읽고/쓰고 싶을 때 재사용 가능한 애들 → lvalue

2. prvalue (pure rvalue)

2-1. 정의

“계산 결과로 나오는 값 자체” / 주로 임시 객체, 리터럴 같은 것

예전 C++에서 말하던 “rvalue”에 제일 가까움

보통 새 객체를 만들거나, 값만 있다가 사라지는 애들

2-2. 예시

10;          // int literal → prvalue
3.14;        // double literal → prvalue
true;        // bool literal → prvalue

int x = 10;
x + 1;       // x + 1 → prvalue

std::string("abc");  // 임시 std::string 객체 → prvalue
S();                 // 임시 S 객체 → prvalue

이 값들은 “메모리 어딘가에 이름 붙은 객체”랑 연결되어 있는 느낌이 아니라,

“계산 결과로 잠깐 존재하는 값”에 더 가깝다 → prvalue

3. xvalue (expiring value)

3-1. 정의

xvalue (expiring value)는:

“곧 수명이 끝나서 자원을 빼앗아도 되는 객체 표현”

“진짜 객체를 가리키긴 하는데, 더 이상 이걸 원래 주인처럼 쓰지 않을 것” 이라는 의미를 가진 값

대표적으로 rvalue reference로 표현된 객체가 xvalue가 됨.

3-2. 예시

std::string make();

std::string s = "hello";
std::string&& r = std::move(s);

r;                // r 자체는 lvalue (이름 있는 변수)
std::move(s);     // 이 표현식 → xvalue
std::move(r);     // 이것도 표현식 → xvalue

std::move(s) 는:

“s라는 실제 객체” (메모리 상에 존재)를 가리키면서

“얘는 이제 곧 자원 뺏어가도 된다”는 의미를 갖는 표현식 → xvalue

즉:

lvalue: “정상적으로 계속 쓸 객체”

xvalue: “아직 존재하긴 하는데, 이제 자원을 뺏어가도 되는 객체”

또 다른 예:

std::vector<int> v = {1,2,3};
v[0];             // lvalue
std::move(v)[0];  // xvalue (이 표현식이 가리키는 원소)

4. glvalue (generalized lvalue)

4-1. 정의

glvalue는:

“메모리 상의 어떤 객체를 가리키는 값”

즉, lvalue ∪ xvalue

다시 말해:

lvalue : 정상적으로 쓰일 객체

xvalue : 곧 만료(expire)될 객체

둘 다 “실제 객체”를 가리킨다는 점에서 공통됨 → 그걸 묶어서 glvalue라고 부름.

4-2. 예시

lvalue 예시: x, s, s.a, v[0]

xvalue 예시: std::move(s), std::move(v)[0]

→ 이걸 전부 glvalue라고 부를 수 있다.

5. rvalue

5-1. 정의

rvalue는:

“주로 임시 객체, 이동 대상(move 대상)”
즉, prvalue ∪ xvalue

예전 C++에서 “rvalue”라고 부르던 녀석들이

C++11 이후에는 prvalue / xvalue로 나뉘고

그 둘을 묶어서 다시 rvalue라고 부르게 된 것.

5-2. rvalue 예시들

10;                   // prvalue → rvalue
x + 1;                // prvalue → rvalue
S();                  // prvalue → rvalue
std::string("abc");   // prvalue → rvalue

std::move(s);         // xvalue → rvalue
std::move(v)[0];      // xvalue → rvalue

정리하면:

prvalue : 값 자체, 새로 만들어지는 임시, 리터럴

xvalue : 실제 객체를 가리키지만 “만료(expiring)된” 상태

이 둘을 합쳐서 → rvalue

6. 포함 관계

glvalue = lvalue ∪ xvalue

rvalue = prvalue ∪ xvalue

즉 xvalue는 glvalue이면서 rvalue에도 포함돼 있다.

0개의 댓글