(Modern C++) forwarding reference

Posted by : at

Category : Cpp


class Knight
{
public:
    Knight() { cout << "기본 생성자" << endl; }
    Knight(const Knight&) { cout << "복사 생성자" << endl; }
    Knight(Knight&&) noexcept { cout << "이동 생성자" << endl; }
};

void Test_RValueRef(Knight&& k)
{

}

int main()
{
    Knight k1;
    Test_RValueRef(k1);             // Error : only r-value
    Test_RValueRef(std::move(k1));  // okay(r-value casting)
}

// && 는 무조건 오른값 참조일까?
// Nope!
template<typename T>
void Test_ForwardingRef(T&& param)  // 이건 r-value 참조인가? -> 전달 참조이다.
{

}

int main()
{
    Knight k1;
    Test_ForwardingRef(std::move(k1));  // okay : T = Knight&&
    Test_ForwardingRef(k1);             // okay : T = Knight&

    auto&& k2 = k1;                     // auto&& : Knight&
    auto&& k3 = std::move(k1);          // auto&& : Knight&&

    // l-value가 들어가면 l-value가 되고
    // r-value가 들어가면 r-value가 된다.
}

단, 이건 안됨

template<typename T>
void Test_ForwardingRef(const T&& param)  // const붙을시 동작하지 않음
{

}

    // ...

    Test_ForwardingRef(std::move(k1));  // error
    Test_ForwardingRef(k1);             // error

근데 이건 언제쓰나?

// 여기서 시작한다
// Func라는 함수를 만들예정인데 r, l value를 모두 받고 싶다면? 함수를 매번 여러 개씩 만들어야 할까?
template<typename T, typename U>
void Func(T&& param, U&& param)     // 이렇게 쓸거라면 4개를 만들어야하나???
{

}

forwarding reference를 쓰자!

template<typename T>
void Test_ForwardingRef(T&& param)
{
    // ...

    // 만약 내부에서 다른 함수를 호출한다면?
    Test_Copy(param);   // T&&가 뭐일지 알고 넘기나???
}
// 우선 오른값과 오른값 참조의 차이를 알고 가자
void Test_RValueRef(Knight&& k)
{

}

Knight& k4 = k1;                // 왼값 참조
Knight&& k5 = std::move(k1);    // 오른값 참조

Test_RValueRef(k4);             // error : 오른값만 받는다
Test_RValueRef(k5);             // error : 역시 오른값만 받는다(참조 안돼)
Test_RValueRef(std::move(k5));  // okay : 오른값으로 만들어줘야한다.

다시 돌아가서

Test_RValueRef(std::move(k1));

template<typename T>
void Test_ForwardingRef(T&& param) /*param 자체는 왼값이다.*/
{
    // ...

    Test_Copy(param);               // param이 복사되며 복사생성자가 호출되게 된다.
    Test_Copy(std::move(param));    // 이동 생성자가 호출된다.
}

// 이건 오른값이 Test_ForwardingRef로 들어왔을때고 왼값이 들어온다면?
Test_RValueRef(k1);

template<typename T>
void Test_ForwardingRef(T&& param)
{
    // ...

    Test_Copy(std::move(param));    // error : 왼값을 함부러 move를 해선안된다.
}

// Test_Copy에 어떻게 넘겨야할까???
// 모두 가능
Test_RValueRef(k1);
Test_RValueRef(std::move(k1));

template<typename T>
void Test_ForwardingRef(T&& param)
{
    // ...

    Test_Copy(std::forward<T>(param));    // 이건 그냥 받아들이자 forward를 써야한다고
    // 왼값 참조면 복사
    // 오른값 참조면 이동
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links