2017-06-30

[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이고 1prvalue이므로 func(std::move(a))func(1)1이 리턴된다.

universal reference

 rvalue reference(&&)처럼 생겼지만, 타입 추론을 해야 하는 경우. 즉, template parameter T가 있을 때 T&&라거나, auto&& 같은 경우 이 타입은 lvalue reference가 될 수도 있고, rvalue reference가 될 수도 있다. 그래서 이런 레퍼런스는 universal reference라고 불린다. 이 universal reference는 bind 되는 값이 lvalue이면 lvalue이면 lvalue reference가 되고, rvalue이면 rvalue reference가 된다. C++의 템플릿 타입 추론에 대해서 설명할 일이 있으면 더 자세히 설명하겠다. 우선은 universal reference는 bind 되는 값이 lvalue인지 rvalue인지에 따라서 어떤 값인지에 따라서 달라진다는 것만 알아두자.

& operator

 lvalue가 rvalue와 다른 중요한 특성 중 하나는 주소를 가지고 오는 & operator의 인자로 lvalue는 사용할 수 있지만, rvalue는 사용할 수 없다는 것이다. 언뜻 생각하면 identity를 가지는 xvalue의 주소를 가지고 오는 것도 가능할 것 같지만, C++11은 & operator의 인자로 올 수 있는 것은 lvalue만이라고 한정하고 있다.

assign operator

 또 다른 특징은 rvalue는 assign operator(=)의 왼쪽에 올 수 없다는 것이다. 조심해야 할 것은 rvalue가 assign operator의 왼쪽에 올 수 있다는 것이지, lvalue가 assign operator의 오른쪽에 올 수 있다는 말은 아니라는 것이다. C++에는 const modifier가 있으므로 모든 lvalue가 assign operator의 왼쪽에 올 수 있지는 않다. 따라서 왼쪽에 올 수 있는 것은 modifiable lvalue라고 따로 분류해서 부른다.


  • 2017-06-30 universal reference 부분을 추가했습니다.

댓글 없음:

댓글 쓰기