원래는 보편 참조(universal reference)였으나 C++17로 넘어오며 명칭이 변경 되었다.
활용할 일이 많지는 않다고 한다.
&&는 무조건 오른값 참조인가? -> X
template, auto같은 형식 연역(type deduction)이 발생할 때만 등장한다.
왼값 참조로 전달하면 왼값 참조, 오른값 참조로 전달하면 오른값 참조로 동작한다.
단, const 같은 키워드가 붙으면 오른값 참조로만 작동한다.
template<typename T>
void Test_ForwardingRef(T&& param) // 전달 참조
// ----
template<typename T>
void Test_ForwardingRef(const T&& param) // 오른값 참조만 가능
오른값 참조에 관한 추가사항
void TestRvalueRef(Knight&& knight) {}
Knight k1;
Knight&& k2 = k1;
Test_RValueRef(k2); // 오류!
k2는 오른값 참조 타입임에도 불구하고 정작 함수에는 넘겨줄수 없다.
그 이유는 오른값 참조 타입은 맞지만 k2자체는 왼값이기 때문이다.
왼값과 오른값의 정의를 잘 생각해보면 무리없이 이해할 수 있다. (왼값: 단일식을 벗어나도 유지되는 값)
void TestRvalueRef(Knight&& knight) {}
Knight k1;
Knight&& k2 = k1;
Test_RValueRef(move(k2)); // OK!
또한, 함수 호출시에 move로 오른값 참조로 만들어서 넘겨줘도 매개변수로 사용할 때 다시 왼값이 되어버린다.
인자로 왼값 참조, 오른값 참조를 넘겨주면 무조건 왼값 참조로 변경된다.
해당 함수 내에서 전달 받았던 그대로 왼값 참조, 오른값 참조로 다른 함수를 호출하려면 forward를 이용하면 된다.
class Knight
{
public:
Knight() { cout << "기본 생성자" << endl; }
Knight(const Knight&) { cout << "복사 생성자" << endl; }
Knight(Knight&&) noexcept { cout << "이동 생성자" << endl; }
};
void Test_Copy(Knight knight)
{
// do something
}
template<typename T>
void Test_ForwardingRef(T&& param) // 전달 참조
{
Test_Copy(forward<T>(param));
}
int main()
{
Knight k1; // 기본 생성자
Test_ForwardingRef(k1); // 복사 생성자
Test_ForwardingRef(move(k1)); // 이동 생성자
return 0;
}
앞으로 전달 참조는 무조건 forward로 받아주면 된다.
'C++ > Rookiss C++' 카테고리의 다른 글
[Modern C++] 스마트 포인터 (smart pointer) -完- (0) | 2022.09.01 |
---|---|
[Modern C++] 람다 (lambda) (0) | 2022.08.31 |
[Modern C++] 오른값 참조 (rvalue reference) (0) | 2022.08.31 |
[Modern C++] #2 (0) | 2022.08.31 |
[Modern C++] #1 (0) | 2022.08.31 |