L value : 한번 호출 후 다시 부를 수 있는 것
R value : 임시적으로 사용하는 값
int a = 10 // a : L-value , 10 : R-value
int b = a // b : L-value , a : L-value
string s = "abc" // s : L-value , "abc" : R-value
L-value 를 R-value 바꿔주는 move 함수도 있다.
std::string c = std::move(a); // L-value 인 a 를 move 를 통해 R-value 로 바꿔준다. (임시 값)
왜 바꿔주는 걸까?
R-value 들은 다시 호출하지 않을 객체들이다.
이렇게 a 를 R-value 로 바꿔주고 c 가 가리키게끔 하면, a 는 해당 값을 c 에게 뺏기게 된다. (ownership 을 넘겨준다)
c 가 힙에 있던 값을 가리키고, a 는 nullptr 혹은 사이즈가 0인 새로운 공간을 가리키게 된다.
일반적으로는 새로운 힙을 가리키지만, string 의 최적화 때문에 size 가 짧아 그냥 스택을 가리킨다고 하는 것이 정확하다.
(저렇게 move 를 통해 R-value 로 변경된 a 를 이후에 사용하지 않아야 한다는 보장이 있어야 한다)
string a = "bconfiden2" // 스택 a -> 힙 "bconfiden2"
string& b = a; // 스택 b -> 힙 "bconfiden2" (a 와 같은 메모리)
string c = move(b); // a 와 b 를 R-value 로 바꾸고 해당 "bconfiden2" 를 c 가 소유
// 이후 a 와 b 는 쓰레기 ~!~!
다만 const 객체는 move 하여 넣더라도 복사가 일어난다.
두 레퍼런스의 차이는 다음과 같다. 사실 그림을 그려서 올리는게 훨씬 이해도 잘되는데,, 아이패드 사고 싶다.
void value(string s) // 스택에 있는 s 가 힙에 있는 새롭게 복사된 "test" 를 가리킴
{
string temp = s; // temp 역시 똑같이 복사됨
}
void L_reference(string& s) // 스택에 있는 s 가 a 와 똑같은 힙 공간을 가리킴
{
string temp = s; // temp 는 복사가 된다!
}
void R_reference(string&& s) // s 가 힙에 있던 임시 객체 "test" 를 가리킴
{
string temp = s; // temp 가 스택에 생기면서 s 가 가리키던 값을 힙에 복사해서 가리킴
string temp = std::move(s) // 이렇게 R-value 로 바꿔줄 경우 복사가 일어나지 않는다!
}
int main(void)
{
string a = "test"; // 스택에 있는 a 가 힙에 있는 "test" 를 가리킴
value(a);
L_reference(a);
R_reference("test"); // 애초에 넘어가는 "test" 는 임시 객체
R_reference(a); // wrong! 레퍼런스를 R-value를 받기 때문에 L-value를 넘겨줄 수 없다
R_reference(std::move(a)) // 이렇게 바꿔 줄 수 있겠다.
}
'STUDY > C++' 카테고리의 다른 글
[C++] 얼리 리턴? (0) | 2020.07.10 |
---|---|
[C++] 배열 형식의 인수 (0) | 2020.06.30 |
[C++] const 포인터와 const 로의 포인터? (0) | 2020.06.29 |
[C++] 키워드 static (0) | 2020.05.26 |
[C++] list 를 쓸까? (0) | 2020.05.22 |