본 글은 공부용으로 작성된 글입니다.
Lvalue와 Rvalue라는것이 있다.
흔히들 Lvalue와 Rvalue는 Left Value와 Right Value라고 말하며 이것은 =기호를 기준으로 왼쪽과 오른쪽에 있는것을 각각 Lvalue와 Rvalue로 말한다.
하지만 C++ 표준에서는 더이상 에서 L과 R은 Left와 Right를 의미하지 않는다.
Lvalue: 단일 표현식 이후에도 없어지지 않고 지속되는 객체
Rvalue: 표현식이 종료된 이후에는 더이상 존재하지 않는 임시적인 값
즉, 쉽게 말해 이름을 가지는 객체는 Lvalue라고 볼 수 있으며
상수 또는 임시 객체는 Rvalue라고 볼 수 있다.
Rvalue는 표현식이 종료된 이후 사라지기 때문에, 어떤 작업을 하는 부분이라고 생각하면 되는데, 이렇게만 보면 이해가 잘 안된다!!!
아래는 이를 설명하기 위한 예시 코드이다.
코드는 https://effort4137.tistory.com/entry/Lvalue-Rvalue 게시글에서 가져왔다.
또한 본 게시글은 위에 링크로 첨부해둔 게시글을 참고하여 이해한 내용을 바탕으로 작성했다.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int x = 3;
const int y = x;
int z = x + y;
int* p = &x;
cout << string("one");
++x;
x++;
}
이름을 가지는 변수는 모두 Lvalue 으로 볼 수 있다.
따라서 x, y, z, p 등 변수들이 Lvalue 이다.
변수에 대입되는 값인 상수값 3, 임시객체 string("one") 은 표현식이 종료되면
더이상 참조할 수 없는 값이기 때문에 Rvalue라고 볼 수 있다.
어떻게 보면 왼쪽 오른쪽으로 나뉘긴 하나, 단순히 왼쪽 오른쪽의 개념이 아닌 다른 개념으로 구분되는 것을 알 수 있었따.
해당 예제에는 주의할 점이 하나 있는데, ++x는 Lvalue인 반면에 x++은 RValue이라는 점이다.
둘 다 증가된 값을 리턴하지만
++x는 증가된 x 자신을 리턴하기 때문에 Lvalue인 반면에 x++은 증가된 복사본을 리턴하기 때문에 Rvalue이라고 한다.
(증감되는 시점이 다른 것은 알고 있었으나, 반환하는 값이 다른것은 처음 알았다! 신기한 사실)
Lvalue와 Rvalue를 굳이 나눈 이유가 무엇인지 궁금해졌다.
이는 객체를 Move 할때 필요한 내용이라고 이해했다.
우선, Move와 Copy가 있는데 이 것을 이해하기 전엔 & 연산자에 대해 먼저 알아두어야 할 것 같다.
C++에서 & 연산자는 Lvalue를 요구하기 때문에 표현식이 Rvalue라면 컴파일 오류가 나게된다.
& 연산자는 메모리주소를 가져와 참조하는 일을 하기때문에, Lvalue를 요구하다보니 표현식 이후 사라지는 Rvalue를 사용하면 오류가 나는 것이다. (없어지는데 주소를 어떻게 가져왕)
따라서, 기본적으로 우리가 C++에서 int& a = b; 형태로 사용하였던 참조자(Reference)는 Lvalue 참조자이다.
C++11 표준에서는 Lvalue 참조자 이외에도 Rvalue를 참조할 수 있는 Rvalue 참조자가 추가되었으며.
Rvalue 참조자는 Visual Studio 2010 이상 버전의 컴파일러에서 사용 가능하다.
여기서 Lvalue와 Rvalue를 구분하여 사용하는 이유를 알 수 있는데,
바로 Move Semantics 사용을 위해서 이다.
Move Semantics란 객체의 리소스(동적으로 할당 된 메모리와 같은)를 또 다른 객체로 전송(이동)하는 것을 의미한다고 한다.
무슨 말인지 모르겠는데, 구글링을 통해 확인해보니 move를 시키면 메모리 주소는 유지되면서 포인터만 바뀌게 되는 반변에 copy는 값을 복사하기 때문에 매번 메모리에 할당이 된다고 한다.
기존 우리가 사용하던 Lvalue에 & 연산자를 붙여 사용하는 방법은 move가 불가하여 copy 방식으로 처리가 이루어지는 것으로 보여진다.
따라서 Rvalue 참조자를 이용하여 임시 객체의 리소스를 이동시킴으로서 쓸데없는 메모리 할당과 복사 작업을 생략하여 성능이 많이 향상되며 이러한 장점을 위해 사용하는 것으로 보여진다.
그 외에도
- lvalue : identity를 가지면서 move될 수 없는 표현식들
- xvalue : identity를 가지면서 move될 수 있는 표현식들
- prvalue : identity를 가지고있지 않으면서 move될 수 있는 표현식들
- glvalue : identity를 가지고있는 표현식들(lvalue, xvlaue모두 glvalue 표현식)
- rvalue : move될 수 있는 표현식들(prvalue, xvalue 모두 rvalue 표현식)
- identity를 가지고 있지 않으면서 move될 수 없는것들
이런 것들이 있는데, 내용이 너무 방대하고 어렵다.. ㅠㅠ
아래 해당 내용은 아래 글을 같이 읽어본다면 도움이 될 것이다.
https://dydtjr1128.github.io/cpp/2019/06/10/Cpp-values.html
댓글