lvalue와 rvalue
Value Category
- 정체를 알 수 있는가
- 해당 식이 다른 식과 같은 것인지 아닌지 구분할 수 있는가?
- 변수 - 주소값을 통해 구분
- 함수 - 이름으로 구분
- 이동 시킬 수 있는가
- 해당 식을 안전하게 다른 곳으로 이동할 수 있는가?
- 이동 생성자, 이동 대입 연산자를 사용할 수 있는지의 여부
이동 가능 이동 불가능 정체를 알 수 있다 xvalue lvalue 정체를 알 수 없다 prvalue 쓸모없음
lvalue
- 좌측값은 어떠한 표현식의 왼쪽, 오른쪽 모두에 올 수 있음
- 이동(move)시킬 수 없음
- 이름을 가진 대부분의 객체들은 모두 lvalue
- 객체의 주소값을 취할 수 있기 때문
int a;
a;
int&& x = a; // error
- 주소값 연산자(&) 를 통해 해당 식의 주소값을 알아 낼 수 있다
- &++i 나 &std::endl 은 모두 올바른 작업
- 또한 lvalue 들은 좌측값 레퍼런스를 초기화 하는데에 사용할 수 있다
- 주의할 점
void f(int&& a) {
a; // lvalue다
}
f(3);
// 식 a의 타입은 우측값 레퍼런스
// 식 a의 값 카테고리는 lvalue -> 이름이 있기 때문
// 따라서, 아래의 식은 컴파일이 가능함
// main.c
#include <iostream>
void f(int&& a) { std::cout << &a; } // a의 주소값 추적 가능
int main() { f(3); }
- lvalue의 범주
- 변수, 함수의 이름, 어떤 타입의 데이터 멤버
// ex) int i; void func1(); std::endl;
- 좌측값 레퍼런스를 리턴하는 함수의 호출식
// ex) std::cout << i; ++it;
- 복합 대입 연산자식
// ex) a = b; a+=b; a*=b;
- 전위 증감 연산자식
// ex) ++a; --a;
- 클래스의 멤버 메서드/변수를 참조할 때 (단, static 메서드도, enum도 아닌 경우)
// ex) class A { int f(); // static 이 아닌 멤버 함수 static int g(); // static 인 멤버 함수 } A a; a.g; // <-- lvalue a.f; // <-- lvalue 아님 (아래 나올 prvalue)
- 배열 참조식
// ex) int a[n];
- 문자 리터럴
// ex) "hi"
- 문자 리터럴의 케이스는 조금 특별하다
- 문자열은 character의 const static 배열이며, 프로그램의 메모리 상에 존재한다
- 분류상 glvalue에 속한다
- xvalues는 될 수 없기에, lvalues로 분류된다
- 변수, 함수의 이름, 어떤 타입의 데이터 멤버
prvalue
- 이동시킬 수 있음
- 주소값을 취할 수 없음
- 우측값은 식의 오른쪽에만, read-only (식의 좌측에 올 수 없음)
- Take the variables themselves, not copying them
- prvalue의 범주
- 문자열을 제외한 리터럴들
// ex) 42, true, nullptr;
- 레퍼런스가 아닌 것을 리턴하는 함수의 호출식
// ex) str.substr(1,2); str1 + str2;
- 후위 증감 연산자식
// ex) a++, b--;
- 산술 연산자식, 논리 연산자식
// ex) // 오버로딩된 연산자 아닌 디폴트 연산자 a + b, a && b, a < b;
- 주소값 연산자식
// ex) &a;
- 클래스의 멤버 메서드/변수를 참조할 때 (단, m이 enum이거나 static 메서드인 경우)
- this
- enum 값
- 익명함수 (람다식)
// ex) []() { return 0;};
- 문자열을 제외한 리터럴들
xvalue
- 좌측값처럼 주소값을 트래킹할 수 있지만, 또한 이동도 할 수 있는 카테고리
- std::move()를 이용해서 우측값 레퍼런스를 리턴하는 호출식
std::move(x); vector<int> a, b = {1,2,3,4,5}; a = b; // a: 1,2,3,4,5 b:1,2,3,4,5 a = std::move(b); // b-> rvalue, a:1,2,3,4,5 b:{}