반응형
lvalue, rvalue에 대한 내용을 제미나이에게 물어본 결과이다.
msdn c++ 관련 문서에도 나와있는 내용.
맞는지 틀린지는 나중에 읽어봐야겠음.
https://learn.microsoft.com/ko-kr/cpp/cpp/lvalues-and-rvalues-visual-cpp?view=msvc-170
값 범주: Lvalues 및 Rvalues(C++)
자세한 정보: Lvalues 및 Rvalues(C++)
learn.microsoft.com
C++ 값 카테고리 (Value Categories)
C++의 값 카테고리(Value Category)는 C++11에서 이동 의미론(Move Semantics)이 도입되면서 더 정교하게 분류되었습니다. 이들은 표현식(expression)이 평가될 때 그 결과가 어떤 종류의 값인지를 나타냅니다.
핵심적인 두 가지 속성은 다음과 같습니다.
- Identity: 값이 메모리 상에서 고유한 주소를 가지고 식별 가능한가? (예: 변수)
- Movability: 값의 리소스를 "훔쳐올" 수 있는가(move)? (예: 임시 객체)
이 두 속성을 기준으로 5가지 값 카테고리를 이해할 수 있습니다.
1. lvalue (엘밸류)
- 정의: Identity가 있고, Move가 불가능한 값입니다. 가장 일반적인 "변수"를 생각하면 됩니다. 이름(주소)을 통해 계속 참조할 수 있습니다.
- 어원: "Left-value" (대입문의 왼쪽에 올 수 있음)에서 유래했지만, 항상 그런 것은 아닙니다.
const
lvalue는 대입문 왼쪽에 올 수 없습니다. - 핵심 특징:
- 주소를 가져올 수 있습니다 (
&
연산자 사용 가능). - 표현식이 끝난 후에도 계속 존재합니다.
- 주소를 가져올 수 있습니다 (
- 예시:
int x = 10; // x는 lvalue int* p = &x; // p와 *p는 lvalue std::string s; // s는 lvalue s[0]; // s의 첫 번째 문자를 가리키는 lvalue
2. prvalue (pure rvalue, 순수 알밸류)
- 정의: Identity가 없고, Move가 가능한 값입니다. 순수한 "값 자체"로, 특정 메모리 위치와 연결되지 않은 임시적인 값입니다.
- 어원: "Right-value" (대입문의 오른쪽에만 올 수 있음)에서 유래했습니다.
- 핵심 특징:
- 주소를 가져올 수 없습니다.
- 표현식이 끝나면 바로 사라집니다.
- 리터럴(literal), 함수가 값으로 반환하는 결과 등이 해당됩니다.
- 예시:
int x = 42; // 42는 prvalue x = 10 + 20; // 10 + 20의 결과(30)는 prvalue std::string s = "hi"; // "hi"는 prvalue get_value(); // 값을 반환하는 함수의 호출 결과는 prvalue
3. xvalue (eXpiring value, 만료되는 값)
- 정의: Identity가 있지만, Move가 가능한 값입니다. 곧 소멸될 예정이라 리소스를 훔쳐가도 되는, "만료 직전의" 값입니다. lvalue를 rvalue처럼 다루고 싶을 때 사용합니다.
- 핵심 특징:
- lvalue처럼 특정 객체를 가리키지만(Identity가 있음), rvalue처럼 이동(move)될 수 있다고 표시된 값입니다.
- 주로
std::move
의 결과나, rvalue 참조(&&
)를 반환하는 함수 호출 결과입니다.
- 예시:
std::string s = "hello"; std::string s2 = std::move(s); // std::move(s)의 결과는 xvalue // s는 이제 "비어있는" 상태가 됨
std::move(s)
는s
자체를 바꾸는 것이 아니라,s
를 xvalue로 캐스팅하여s
의 리소스를 "이동"할 수 있도록 허용하는 표현식을 만듭니다.
카테고리 그룹
위 세 가지 기본 카테고리를 묶어서 두 개의 상위 카테고리를 만듭니다.
4. glvalue (Generalized lvalue, 일반화된 엘밸류)
- 정의: Identity가 있는 모든 값을 의미합니다. 즉, lvalue와 xvalue를 포함하는 더 넓은 개념입니다.
- 공식:
glvalue = lvalue + xvalue
5. rvalue (알밸류)
- 정의: Move가 가능한 모든 값을 의미합니다. prvalue와 xvalue를 포함하는 더 넓은 개념입니다. 함수 오버로딩에서 rvalue 참조(
&&
)가 바인딩될 수 있는 값들입니다. - 공식:
rvalue = prvalue + xvalue
표로 정리
이 관계를 표로 보면 명확하게 이해할 수 있습니다.
Has Identity (식별 가능) | No Identity (식별 불가) | |
---|---|---|
Movable (이동 가능) | xvalue | prvalue |
Not Movable (이동 불가) | lvalue | (해당 없음) |
- glvalue: "Has Identity" 열 전체 (
lvalue
+xvalue
) - rvalue: "Movable" 행 전체 (
xvalue
+prvalue
)
왜 중요한가?
이러한 구분은 함수 오버로딩과 이동 의미론에서 결정적인 역할을 합니다. 컴파일러는 표현식의 값 카테고리를 보고 어떤 버전의 함수를 호출할지 결정합니다.
void process(const std::string& s) {
// lvalue를 위한 함수 (복사 또는 const 참조)
std::cout << "lvalue version" << std::endl;
}
void process(std::string&& s) {
// rvalue를 위한 함수 (이동)
std::cout << "rvalue version" << std::endl;
std::string new_s = std::move(s); // s의 리소스를 이동
}
int main() {
std::string my_str = "hello";
process(my_str); // my_str은 lvalue -> lvalue 버전 호출
process("world"); // "world"는 prvalue (rvalue) -> rvalue 버전 호출
process(std::move(my_str)); // std::move(my_str)은 xvalue (rvalue) -> rvalue 버전 호출
}
출력:
lvalue version
rvalue version
rvalue version
반응형
'개발 > C++' 카테고리의 다른 글
[모던 C++] 배열 대신 std::vector, std::array를 써보자 (0) | 2025.07.06 |
---|---|
[C++] std::variant 쓰는 법 (0) | 2025.03.16 |
댓글