게임 개발 메모장
[ C++ ] L-Value / R-Value 래퍼런스 본문
C언어에는 lvalue(left value), rvalue(right value) 라는 개념이 존재한다.
이 왼쪽 값, 오른쪽 값이란 단어의 의미는 매우 직관적으로 등호 (=) 의 왼쪽에 있으면
lvalue , 오른쪽에 있으면 rvalue 이다.
대입받는 값, 대입되는 값이라고도 할 수 있다.
lvalue
표현식 이후에도 사라지지 않는 값. 이름을 지니는 변수.
rvalue
표현식 이후에는 사라지는 값. 임시 변수.
굵은 밑줄이 쳐진 것이 rvalue 이다.
x+y 따위는 실제 변수가 아니라 임시 변수를 생성하여 (레지스터인지 메모리인지)에 저장, 사용한다.
이 값은 일반 변수와 마찬가지로 int 등의 타입을 가지고 있지만
계산이 끝나면 사라지는데 이것이 rvalue 이다.
그리고 명시적으로 선언하여 '이름'을 가지고, 계속 접근할 수 있는 변수가 바로 lvalue 이다.
lvalue에 약간의 연산을 가한 것, 포인터(주소값)등은 따로 저장되어 있는 변수가 아니라
'연산된 결과' 이기에 전부 rvalue 라고 볼 수 있겠다.
함수 리턴 값 따위 또한 rvalue이다.
하나 신기했던 것은 ++x 와 x++의 차이인데, x++ 을 쓸 때를 생각해 보면 이렇다.
위 코드에서, 2번째 줄을 보자.
a는 11로 변경되었지만 b에 대입되는 값은 10이다.
즉 계산식에서 의미하는 a의 값과 계산 후 a가 지니는 값이 다르다.
이 계산식의 의미가 'a의 값을 계산에 사용한 다음에' , 'a의 값을 변화시킨다' 인 줄 알았지만 그게 아니었다.
보다 직관적인 방법으로 'a의 값을 카피하여 임시 변수(rvalue)에 저장하고' ,
'원래 a(lvalue)의 값을 변경' , '그리고 임시 변수를 계산에 사용' 이라는 방법이었던 것이다.
그렇기 때문에 x++ 과 같은 경우 rvalue, 임시변수이다. x와는 다른 변수인 것.
이렇게 직관적이지 않은 경우를 위한 구분 방법이 있다.
주소값을 가져오는 & 연산자가 있는데,
이 연산자는 이름이 있는 변수인 lvalue의 주소를 가져오는 연산자이다.
그렇기 때문에 &(rvalue)를 쓰면 컴파일 에러가 난다.
또한 나는 그다지 자주 사용하지 않았지만 c에는 참조 변수라는 것이 있다.
int& a= b; 와 같이 사용하는 것 말이다.
이건 일종의 포인터를 가져와 같은 변수로 사용하는 용법인데
이것 또한 위 &연산자와 마찬가지로 b가 rvalue 이면 에러가 난다.
그 상황을 위해서 c++11에서 새롭게 추가된 참조자가 && 이다. int&& a = 10; 따위로 사용 가능하다.
그런데 이게 왜 필요할까? 그걸 위해서는 move semantics 라는 걸 알 필요가 있다.
이게 무슨 개념인가 하면, 객체의 리소스(동적 메모리 등)을 다른 객체로 이동하는 것을 말한다.
이게 제대로 된 해석인가는 정확하지 않다는 걸 먼저 짚어두고,
내가 이해하기로는 특정 구조체의 값을 다른 구조체로 옮기고자 할 때
각각의 멤버 변수를 전부 copy 하는 게 아니라 포인터 변수를 사용, 가리키는 방식으로 옮기는 것이라고 이해했다.
즉 기존의 메모리 위치에 써있는 rvalue를 lvalue가 잡고있는
메모리 위치에 써주는 게 아니라, lvalue가 기존에 rvalue가 잡고 있던 위치를 대신 사용하는 것이다.
메모리 주소공간에 있는 데이터의 변수 이름이 비어있으니(rvalue) 변수 이름을 적어준다(lvalue화)고 봐도 될 것 같다.
아무튼 저런 과정을 거침으로 해서 불필요한 연산이 줄어들고, 확실하게 성능이 향상된다고 한다.
그리고 당연하다면 당연하겠지만 lvalue, 이미 이름을 가진 변수는 move semantic을 사용할 수 없다.
책을 보다가 본 유의사항으론, rvalue와 lvalue를 쉽게 혼동할 수 있는 경우가 있다고 한다.
int &&a = 10; 에서 a는 rvalue를 가리키지만, 그렇다고 해서 a가 rvalue인 것은 아니다. a는 lvalue이다.
마치 포인터가 특정 구조체를 가리킨다고 해서 구조체가 아니며 4byte void* 타입인 것과 동일하다고 보면 될 것 같다.
'언리얼 엔진 > C++' 카테고리의 다른 글
[ C++ ] 게임에서 동기와 비동기 예시 (0) | 2024.01.01 |
---|---|
[ C++ ] TTuple (0) | 2023.12.30 |
[ C++ ] 가상 소멸자(Virtual Destructor) (0) | 2023.12.24 |
[ C++ ] 가상 상속 (0) | 2023.12.24 |
[ C++ ] 가상 함수와 가상 함수 테이블 (0) | 2023.12.24 |