C++

[C++] LValue vs RValue. 총 정리

sseram 2023. 5. 16. 15:26
반응형

2023.04.29 - [C++/기타] - [C++] LValue vs RValue (1)

 

[C++] LValue vs RValue (1)

맨 첨에 C를 어정쩡하게 배운 후에 C++ 사용하다 보니 애매하게 이해가 되기도 했고.. 지금도 어느 정도 쓰고 있긴 하지만 아직까지 제대로 감이 잡히지 않아, 공부하며 정리할 겸 남겨본다. https:/

donot-simsim.tistory.com

 

2023.05.10 - [C++/기타] - [C++] LValue vs RValue (2)

 

[C++] LValue vs RValue (2)

2023.04.29 - [C++/기타] - [C++] lValue vs rValue (1) [C++] LValue vs RValue (1) 맨 첨에 C를 어정쩡하게 배운 후에 C++ 사용하다 보니 애매하게 이해가 되기도 했고.. 지금도 어느 정도 쓰고 있긴 하지만 아직까지

donot-simsim.tistory.com

 

2023.05.15 - [C++/기타] - [C++] LValue vs RValue (3)

 

[C++] LValue vs RValue (3)

2023.05.10 - [C++/기타] - [C++] LValue vs RValue (2) [C++] LValue vs RValue (2) 2023.04.29 - [C++/기타] - [C++] lValue vs rValue (1) [C++] LValue vs RValue (1) 맨 첨에 C를 어정쩡하게 배운 후에 C++ 사용하다 보니 애매하게 이해가

donot-simsim.tistory.com

 

 

 

(1) 에서는 lvalue는 식의 왼 쪽에 올 수 있는 값, rvalue는 식의 오른 쪽에 올 수 있는 값이라고 정의했다.

 

애초에 lvalue, rvalue의 어원이 left value, right value라고 했었으니 당연히 맞는 말이다. 다만 현재 이 개념만으로 lvalue, rvalue를 정의하기엔 뭔가 애매하다. 처음 봤던 value들의 표를 보면 xvalue도 rvalue 의 한 속이지만, getText() = "aaa"; 이런 식으로 xvalue도 식의 왼 쪽에서 사용이 가능하다.

 

그래서 다른 방식으로 lvalue, rvalue를 구분한다고 한다.

 

 

(2), (3) 에서 xvalue의 두 가지 특성이라고 했던

 

- 본인의 고유한 주소를 가지고 있다.

- 값이 moveable 하다.

 

이 두 가지를 가지고 구분을 한다고 한다.

 

 


  • 고유한 주소를 가지고 있다.

 

 

1.

has identity. 메모리 상에서 내 실제 위치가 있고, 그 안에 어떠한 값이 들어가 있다.

어떠한 변수, 혹은 식을 가지고 있고, 해당 주소 안에 나만의 값을 가지고 있다.

int a = 3; 이런 게 있다면 

a 변수는 그 주소가 있을 것이고(has identity), a의 값을 가지고 있어 다른 변수, 혹은 식과 비교가 가능하다. (a == 3, a > 2)

 

 

 

2.

xvalue에서 예시로 들어 설명했던 함수 식들도 고유한 주소를 가지고 있다.

myClass makemyClass() {
	return myClass(5);
}

int main() {
	myClass m1class;
	m1class = makemyClass();
	return 0;
}

makemyClass()를 통해 return받은 값은 myClass(5)라는 고유한 값을 가지고 있다. 그리고 해당 값은 주소를 가지고 있기 때문에, 사용자는 모르지만 컴파일러는 해당 주소를 활용할 수 있으며

myClass makemyClass() {
	return myClass(5);
}

int main() {
	makemyClass() = myClass(3);
	return 0;
}

이런 식으로, 그 주소에 다른 값들도 넣을 수 있다. 물론 expiring value라는 이름에 맞게 해당 라인이 지나가면 바로 사라지긴 하지만, 중요한 것은 본인의 고유한 주소를 가지고 있다는 점이다.

 

 

 

3.

다만, prvalue 라고 불리우는 값들은 고유한 주소를 가지고 있지 않다.

예를 들어 int a = 3; 이라고 했을 때, 3이라는 값은 그냥 3 자체일 뿐이다. 어떠한 주소에 저장되어 있지 않고, 그저 3이라는 값을 나타낼 뿐이다.

 

 


  • 값이 moveable 하다.

 

 

 

1. 

변수에 있는 값들은 기본적으로 이동 할 수 없다. (3)에서 정리한 글을 봤듯, move가 효율적이려면 본인의 값을 복사하지 않고 넘겨줘야 한다. 이 때 본인이 가지고 있는 값은 사라진다.

myClass makemyClass() {
	return myClass(5);
}

int main() {
	myClass m1class(4);
	myClass m2class(5);

	m1class = m2class;

	cout << m1class.mynum << endl;

	return 0;
}

위의 m1class = m2class 라는 식을 수행할 때, m2class에 있는 값들을 복사하여서 m1class에 넘겨 줄 것이다. 값을 이동시키면 본인의 값이 사라지기 때문에, 기본적으로 이동 가능하지 않다.

 

 

 

2.

다만 xvalue에 있는 값들은 이동 가능하다.

myClass makemyClass() {
	return myClass(5);
}

int main() {
	myClass m1class(4);
	m1class = makemyClass();

	return 0;
}

이동을 하지 못하는 이유는, 값을 이동시키고 나면 원본의 변수는 아예 없는 값이 되므로 사용할 수 없게 되어서이다. 하지만 expiring value, 즉 어차피 없어질 값이었다면 문제가 되지 않는다. 단점은 사라지고, 장점만 남게 된다.

그러므로 xvalue에 있는 값들은 이동 가능하다.

 

 

 

3.

prvalue들도 (3, 4.1f, "sometext")이동이 가능하다. 어차피 상수 값들이니, 언제든지 가져다 쓰면 된다.

 

 

 


 

위 두 가지의 정리를 생각하며, 맨 처음 봤던 그래프를 다시 한 번 보자.

그리고 위에서 설명했던 특성을 가지고 해당 값들을 다시 나눌 것이다.

 

고유한 주소를 가지고 있다         -> i

고유한 주소를 가지고 있지 않다 -> I

 

moveable이다                             -> m

moveable 하지 않다                    -> M

 

 

 

그러면 아래와 같이 나온다.

 

lvalue는 iM

rvalue는 m (im, Im) 으로 나타낼 수 있다.

 

 

 

즉,

lvalue는 has identity. 본인의 주소를 가지고 있지만 이동이 불가능한 것들을 뜻한다.

rvalue는 이동이 가능하기만 한 것들이며, identitiy는 신경쓰지 않는다.

 

 

 

 

결론:

 

lvalue와 rvalue의 첫 시작은 식의 왼 쪽, 식의 오른 쪽에서 사용한다는 것이 맞았다. 하지만 modern c++로 오면서 이렇게 나누는 방법은 더이상 맞지 않게 되어 새로운 구분 방식이 필요해졌다. 그렇게 나온 것들이 identity / moveable 의 특성을 확인하는 것이라고 한다.

물론 해당 구분을 몰라도 C++로 구현하는 데에는 큰 상관이 없다. 다만 효율이 좋고 속도가 빠른 C++ 를 제대로 사용하기 위해서는, 추후 C++에서 사용되는 여러 스킬들을 제대로 알고 사용하기 위해, 적어도 C++이 값이 어떤 방식으로 사용되는지는 알아야 하지 않냐는 생각이다. 

 

 

 

 

 

 

 

* 잘못된 정보는 알려주신다면 감사한 마음으로 수정하겠습니다.

반응형