*전달 참조 ( forwarding reference ) = 보편 참조 ( universal reference )
( template, auto 와 연관 )
=> std::forward 를 사용해야함.
std::move : r-value 를 반환. (즉, class<T>&& 로 캐스팅하는 용도 )
* 특수 템플릿 인자 유추 규칙
A&& // -> A&
A&&& // -> A&
A&&& // -> A&
A&&&& // -> A&&
template <typename T>
void foo(T&& A);
A : 좌측값 ( l-value ) 라면,
T&& + &A = T&&& = T&.
A : 우측값 ( r-value ) 라면,
T&& + &&A = T&&&& = T&&.
* && 이 무조건 오른값 참조여야만 하나 ??
=> 형식 연역 ( type deduction = 타입추론 ) 할 때, 약간의 문제가 있을 수 있다.
ex) auto , template
void Test_RValueRef(Knight&& k) => ( 오른값 참조 )
{
}
template<typename T>
void Test_ForwardingRef(T&& param) => ( 전달참조 )
{
}
Knight k1;
Test_ForwardingRef(std::move(k1)); // (knight&&)
Test_ForwardingRef(k1); // (knight&)
auto&& k2 = k1; // (knight&)
auto&& k3 = std::move(k1); // (knight&&)
=> 왼값을 넣으면 왼값참조 / 오른값을 넣으면 오른값참조로 동작
=> 둘 다 넣어질 수 있음.
template<typename T>
void Test_templateRValueRef(const T&& param) // const
{
}
//Test_templateRValueRef(k1); => ERROR
Test_templateRValueRef(std::move(k1)); // (knight&&)
=> const 를 붙이면 오른값 참조
*왜 Lvalue, Rvalue 두 가지를 같이 받을 수 있는 전달참조를 따로 만들었을까 ??
Rvalue / Lvalue 따로 만들면 안되었나??
=> 효율성 문제.
l-value / r-value 를 구분해야한다면
템플릿에서 여러 타입을 정의할 시(ex. T1, T2... ), 함수를 여러 개 만들어야 한다.
( T1&& A, T2&& B ) 만 해도 4개를 만들어야한다.
*l-value / r-value 가 같이 들어오는 상황을 어떻게 처리할까 ??
Knight k1;
Knight& k4 = k1;
Knight&& k5 = std::move(k1);
Test_RValueRef(k5); // ERROR,
Test_ForwardingRef(k5); // (Knight&)
Test_ForwardingRef(std::move(k5)); // (Knight&&)
=> k5 처럼 r-value 가 변수로 선언되면 타입은 r-value 가 맞지만, k5 자체는 l-value 가 됨.
따라서, 한번 더 std::move 를 해주어야 r-value 참조로 들어간다.
* std::forward
template <class S>
S&& forward(typename remove_reference<S>::type& a) noexcept {
return static_cast<S&&>(a);
}
void TestCopy(Knight k) {}
template<typename T>
void Test_ForwardingRef(T&& param)
{
TestCopy(std::forward<T>(param));
// 왼값 참조라면 복사 => TestCopy(param);
// 오른값 참조라면 이동 => TestCopy(std::move(param));
}
=> 만약, param 에 & 타입이 들어왔으면 함부로 move 하면 안된다.
왜냐하면 &, && 둘 다 들어오는 상황이므로.
=> std::forward 를 사용해 두 가지 경우를 한번에 처리할 수 있다.
본 내용은 인프런의 루키스님 강의를 듣고 정리한 내용입니다.
'프로그래밍 > C++' 카테고리의 다른 글
#69. c++ 스마트 포인터 ( smart pointer ) (0) | 2022.07.23 |
---|---|
#68. 람다 (lambda) (0) | 2022.07.22 |
#66. 오른값참조 ( rvalue reference ) (0) | 2022.07.22 |
#65. enum class & override & final (0) | 2022.07.22 |
#64. using (0) | 2022.07.22 |