programing tip

std :: move와 std :: forward의 차이점은 무엇입니까?

itbloger 2020. 6. 8. 21:03
반응형

std :: move와 std :: forward의 차이점은 무엇입니까?


나는 이것을 보았습니다 : 기본 클래스 이동 생성자를 호출하는 이동 생성자

누군가 설명 할 수 있습니까?

  1. 차이 std::movestd::forward, 바람직하게는 일부 코드 예에?
  2. 쉽게 생각하는 방법과 사용시기

std::move객체를 가져 와서 임시 (rvalue)로 처리 할 수있게합니다. 시맨틱 요구 사항은 아니지만 일반적으로 rvalue에 대한 참조를 승인하는 함수는이를 무효화합니다. 이 표시되면 std::move나중에 개체 값을 사용해서는 안되지만 새 값을 할당하고 계속 사용할 수 있습니다.

std::forward호출자가 전달하는 데 사용한 템플릿 함수 매개 변수 (함수 내부)를 값 범주 (lvalue 또는 rvalue)로 캐스팅하는 단일 사용 사례가 있습니다. 이를 통해 rvalue 인수는 rvalue로 전달되고 lvalue는 "완벽한 전달"이라는 스키마 인 lvalue로 전달됩니다.

하려면 설명 :

void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
void overloaded( int && arg ) { std::cout << "by rvalue\n"; }

template< typename t >
/* "t &&" with "t" being template param is special, and  adjusts "t" to be
   (for example) "int &" or non-ref "int" so std::forward knows what to do. */
void forwarding( t && arg ) {
    std::cout << "via std::forward: ";
    overloaded( std::forward< t >( arg ) );
    std::cout << "via std::move: ";
    overloaded( std::move( arg ) ); // conceptually this would invalidate arg
    std::cout << "by simple passing: ";
    overloaded( arg );
}

int main() {
    std::cout << "initial caller passes rvalue:\n";
    forwarding( 5 );
    std::cout << "initial caller passes lvalue:\n";
    int x = 5;
    forwarding( x );
}

Howard가 언급했듯이이 두 함수가 단순히 참조 유형으로 캐스트되기 때문에 유사성이 있습니다. 그러나 rvalue 참조 캐스트의 유용성의 99.9 %를 다루는 이러한 특정 사용 사례를 벗어나면 static_cast직접 사용 하고 수행중인 작업에 대한 적절한 설명을 작성해야합니다.


모두 std::forwardstd::move아무것도하지만, 캐스트를하지 않습니다.

X x;
std::move(x);

위의 내용 x은 X 유형 의 lvalue 표현식 을 X 유형의 rvalue 표현식 (정확한 xvalue)으로 캐스트합니다. movervalue를받을 수도 있습니다 :

std::move(make_X());

이 경우 항등 함수입니다. X 유형의 rvalue를 가져 와서 X 유형의 rvalue를 반환합니다.

함께 std::forward사용하면 어느 정도 대상을 선택할 수 있습니다 :

X x;
std::forward<Y>(x);

xX 유형 의 lvalue 표현식 을 Y 유형의 표현식으로 캐스트합니다 . Y에 대한 제한 사항이 있습니다.

Y는 액세스 가능한 X의 Base 또는 X의 Base에 대한 참조 일 수 있습니다. Y는 X 또는 X에 대한 참조 일 수 있습니다.을 사용하여 cv 한정자를 캐스트 할 수는 없지만 cv 한정자를 forward추가 할 수 있습니다. Y는 액세스 가능한 Base 변환을 통한 경우를 제외하고 X에서 간단히 변환 할 수있는 유형일 수 없습니다.

Y가 lvalue 참조이면 결과는 lvalue 표현식이됩니다. Y가 lvalue 참조가 아닌 경우 결과는 rvalue (정확한 xvalue)식이됩니다.

forwardY가 lvalue 참조가 아닌 경우에만 rvalue 인수를 사용할 수 있습니다. 즉, rvalue를 lvalue로 캐스트 할 수 없습니다. 이는 안전상의 이유로 일반적으로 매달려있는 참조로 이어지기 때문입니다. 그러나 rvalue를 rvalue로 캐스팅하는 것은 괜찮으며 허용됩니다.

허용되지 않는 것으로 Y를 지정하려고하면 런타임이 아닌 컴파일시 오류가 발생합니다.


std::forward함수에 전달 된 방식대로 매개 변수 전달 하는 데 사용됩니다 . 여기에 표시된 것처럼 :

언제 std :: forward를 사용하여 인수를 전달합니까?

Using std::move offers an object as an rvalue, to possibly match a move constructor or a function accepting rvalues. It does that for std::move(x) even if x is not an rvalue by itself.

참고URL : https://stackoverflow.com/questions/9671749/whats-the-difference-between-stdmove-and-stdforward

반응형