On this page
article
C++ Rvalue Reference & Reference Rule
Rvalue Ref
필요성
- C++11부터 등장한 Move Semantics와 Forwarding을 위해 도입.
- 상수성 없이 rvalue를 받을 수 있는 문법 필요 →
rvalue reference
(T&&
)
Reference 규칙
- lvalue reference: lvalue만 바인딩.
- const lvalue reference: lvalue, rvalue 모두 바인딩 가능.
- rvalue reference (
T&&
): rvalue만 바인딩.
예시
void foo(Point& pt); // lvalue ref
void foo(Point&& pt); // rvalue ref
Point pt{1, 2};
Point& r1 = pt; // lvalue ref
foo(r1); // foo(Point&) 호출
Point&& r2 = Point{1, 2}; // rvalue ref
foo(r2); // r2는 lvalue, foo(Point&) 호출
foo(static_cast<Point&&>(r2)); // rvalue로 캐스팅 → foo(Point&&)
foo(static_cast<Point&&>(pt)); // lvalue를 rvalue로 캐스팅 → foo(Point&&)
foo(static_cast<Point>(pt)); // 복사본 생성 → foo(Point&&)
rvalue reference
타입으로 선언해도 변수 이름이 있으면 lvalue.static_cast<T&&>
를 통해 rvalue로 변환 가능.
Reference Collapsing
규칙
- ref to ref는 일반적으로 불가능.
- 그러나 typedef, decltype, template parameter에서는 ref to ref 가능.
- Reference collapsing 규칙:
T& &
→T&
T& &&
→T&
T&& &
→T&
T&& &&
→T&&
고려할 상황
- 아래의
f4(n)
호출 시 n이 lvalue면 T = int&로 추론되어f4(int&)
가 호출. 인자가 lvalue이면 → T는 lvalue reference (int&)가 되기때문. 이는 frowarding ref 지원을 위해
Forwarding Reference
정의
T&&
형태의 템플릿 인자가 lvalue와 rvalue를 모두 받을 수 있는 레퍼런스.- 상수성 없이, 복사본 없이 lvalue와 rvalue를 모두 받는 함수를 만들 수 있음.
사례
template<typename T>
void f4(T&& arg) {}
int main() {
int n = 1;
f4<int>(1); // f4(int&&)
f4<int&>(n); // f4(int&)
f4(1); // T = int → f4(int&&)
f4(n); // T = int& → f4(int&)
}
중요성
- Perfect Forwarding, Move Semantics를 구현하는 핵심.
Forwarding Reference vs Overloading
- Overloading으로 lvalue ref, rvalue ref 버전을 각각 만들 수 있지만, 코드 중복.
- Forwarding Reference로 하나의 함수에서 모두 처리 가능.
MISC
const T&&
- const rvalue reference → rvalue만 전달 가능 + 상수성 부여.
- 하지만 사용 빈도는 거의 없음.
auto&&
- **
auto&&
**는 Forwarding Reference와 동일한 역할. - C++20 이후, 함수 인자로
auto&&
사용 가능:
void f1(T&& arg);
void f2(auto&& arg); // 동일
- template 추론 규칙 적용.