상세 컨텐츠

본문 제목

[C++11] Rvalue references

C++/Modern C++(11, 14, 17, 20)

by deulee 2023. 8. 28. 15:54

본문

"Rvalue reference"는 C++11에서 도입된 기능으로 오로지 Rvalue에만 할당될 수 있는 새로운 레퍼런스이다.

 

이를 선언하는 방법은 다음과 같다.

T&& // where T is non-template type parameter (such as int, or a user-defined type)

 

그럼 "Rvalue reference"가 어떻게 바인딩되는지 확인해보자.

#include <iostream>

int main(void)
{
	int x = 0; // `x` is an lvalue of type `int`
	int& xl = x; // `x1` is an lvalue of type `int&`
	int&& xr = x; // error -- `x` is an lvalue
	int&& xr2 = 0; // `xr2` is an lvalue of type `int&&` -- binds to the rvalue temporary, `0`

	void f(int& x) {}
	void f(int&& x) {}

	f(x); // calls f(int&)
	f(xl); // calls f(int&)
	f(3); // calls f(int&&)
	f(std::move(x)); // calls f(int&&)

	f(xr2); // calls f(int&)
	f(std::move(xr2)); // calls f(int&&)
	return 0;
}

"Rvalue Reference"는 위와 같은 규칙을 가지게 된다.

 

그럼 다음과 같은 의문점이 생길 수 있다. 왜 `f(xr2)`는 `f(int&)` 함수를 호출하는 것일까? 분명한 것은 `xr2`의 타입이 `int&&`로 선언되었는데 말이다.

 

우선 Rvalue와 Lvalue의 차이점을 알 필요가 있다.


Rvalue vs Lvalue

Rvalue와 Lvalue는 이름에서도 나오듯이 차이점이 뚜렷한 "값 카테고리"다.

 

그럼 어떤 부분에서 차이가 있을까?

 

Lvalue

  • lvalue는 "메모리에서 위치를 가지는 변수나 객체"를 나타냄.
  • 변수의 이름이나 객체의 이름은 lvalue이다.
  • lvalue는 주소를 가지며, 해당 주소를 통해 값을 변경하거나 접근할 수 있다.
  • ex) 변수 `x`, 배열 요소 `arr[3]`, 클래스 객체 `obj`

Rvalue

  • rvalue는 "메모리에서 위치를 가지지 않는 일시적인 값"을 나타냄.
  • 임시적인 값을 나타내거나, 표현식의 결과 값이나 상수 등이 rvalue이다.
  • rvalue는 주소를 가지지 않으며, 일반적으로 임시적으로 생성되는 값이다.
  • ex: 리터럴 상수 `42`, 표현식 `x + y`, 함수 호출 결과 `getNumber()`

그럼 이제 위의 예제에서 `int&& z = 0`에서 `f(z)`를 호출할 때 `f(int&)`가 호출되는지 설명하도록 하겠다.

 

앞서 설명했듯이, rvalue는 임시적인 값(메모리에서 위치를 가지지 않는 값)을 의미했다.

 

하지만 `main` 함수의 scope에서는 "rvalue"의 타입으로 선언된 변수 `z`는 더 이상 임시적인 값이 아니다. 즉, 메모리에서 위치를 가지고 있는 것이다. 이 말은 변수 `z`는 "rvalue"의 타입으로 초기화되었지만 "lvalue"의 속성을 가지게 된다.

 

그러므로 `f(int&)`가 호출되는 것이다.

관련글 더보기