6월, 2017의 게시물 표시

[C++] lvalue와 rvalue

지난번 글에서 C++의 value category에 관하여 설명하였다. 요약하면 다른 값으로 move될 수 있는지와 identity를 가지는지에 따라서 lvalue, xvalue, prvalue로 나뉘고, lvalue와 xvalue를 합쳐서 glvalue, xvalue와 prvalue를 합쳐서 rvalue라고 부른다는 것이다.
 앞에서도 말했듯이 C++의 value category를 나누는 기준은 move 될 수 있는지와 identity를 가지는지 여부이다. 이중 iM은 lvalue라고 부르고, im인 xvalue와 Im인 prvalue를 합쳐 rvalue라고 부른다. identity를 가지지도 않고, move 될 수도 없는 IM은 C++에 존재하지 않기 때문에 사실상 lvalue와 rvalue를 나누는 기준은 move 될 수 있는지 아닌지이다. 따라서 move 될 수 없으면 lvalue이고, move될 수 있으면 rvalue이다. 이번 글에서는 그래서 lvalue와 rvalue가 구분되는 특성을 설명할 것이고 다음 기회에 glvalue와 prvalue가 구분되는 특성을 설명하도록 하겠다.overloaded function 우선 lvalue와 rvalue의 가장 중요한 차이는 overload 된 함수가 있을 때 어떤 함수가 호출될지가 달라진다는 것이다.
위처럼 같은 타입의 lvalue reference를 받는 함수와 rvalue reference를 받는 함수가 overload돼있을 때, argument가 lvalue이면 lvalue reference를 받는 함수가 호출되고, rvalue이면 rvalue reference를 받는 함수가 호출된다.
따라서 위와 같이 사용했을 때, func(a)는 a가 lvalue이므로 0이 리턴되지만, std::move(a)는 xvalue이고 1은 prvalue이므로 func(std::move(a))와 func(1)은 1이 리턴된다.universal reference rvalue reference(&&)처럼 생겼지만,…

왜 c++은 복잡한 value category를 가지게 됐는가

C++11이 나오기 전, C++의 value category는 lvalue와 rvalue만으로 이루어진 단순한 분류체계를 가지고 있었다. 하지만 C++11이 나오면서 xvalue, glvalue, prvalue가 추가되면서 복잡한 분류체계를 가지게 됐다. 이번 글에서는 C++11에서 변경된 value category에 대해서 알아보도록 하겠다.until c++03 C++11에서 새로 추가된 value들을 알기 전에 C++03 이전에도 있었던 lvalue와 rvalue가 뭔지부터 확실히 하고 넘어가야 한다. 흔히들 많이 실수하는 것이 lvalue는 assign operator(operator =)의 왼쪽에 올 수 있는 값이고, rvalue는 올 수 없는 값이라고 생각하는 것이다. C에서 lvalue라는 개념이 처음 나왔던 시절에는 assign operator를 기준으로 lvalue인지 아닌지를 구분하는 것이 맞았다. 하지만 C89에서 const 한정자가 추가되면서 더는 맞지 않다. const variable은 lvalue이지만 assign operator의 왼쪽에 올 수 없기 때문이다.
 따라서 C89에서는 lvalue를 left value가 아닌 locator value. 즉, 실제 값이 아닌 값이 있는 주소를 지칭하는 locator value라고 정의했다. 즉, 변수는 locator이기 때문에 lvalue이고, 1, 2 같은 숫자 리터럴이나 'a', 'b' 같은 문자 리터럴, 혹은 함수의 실행 결괏값 같은 경우 특정한 주소를 지칭하는 locator가 아니므로 lvalue가 아니다. 이 중에서 const 한정자가 붙지 않은 경우를 modifiable lvalue라고 따로 분류하여, modifiable lvalue만 assign operator의 왼쪽에 올 수 있다. 후에 나온 C++98도 C89의 lvalue 정의를 따랐기 때문에 C++98에서의 lvalue도 locator 라고 보면 된다. 다만 C89와 다르게 레퍼런스를 리턴…