Programing

RValue Reference (&&)의 반환이 유용한 경우가 있습니까?

lottogame 2020. 10. 25. 11:29
반응형

RValue Reference (&&)의 반환이 유용한 경우가 있습니까?


함수 가 RValue 참조를 반환해야하는 이유가 있습니까? 기술, 속임수, 관용구 또는 패턴?

MyClass&& func( ... );

나는 일반적 으로 참조반환 하는 위험을 알고 있지만 때때로 우리는 어쨌든 그것을합니다. 그렇지 않습니다 ( T& T::operator=(T)관용적 예입니다). 하지만 T&& func(...)어때요? 그렇게함으로써 얻을 수있는 일반적인 장소가 있습니까? 클라이언트 코드와 비교하여 라이브러리 또는 API 코드를 작성할 때 아마도 다를 수 있습니까?


적절한 경우가 몇 가지 있지만 비교적 드뭅니다. 클라이언트가 데이터 멤버에서 이동할 수 있도록 허용하려는 경우 한 가지 예가 있습니다. 예를 들면 :

template <class Iter>
class move_iterator
{
private:
    Iter i_;
public:
    ...
    value_type&& operator*() const {return std::move(*i_);}
    ...
};

이것은 towi의 의견에 이어집니다. 지역 변수에 대한 참조를 반환하고 싶지 않습니다. 그러나 당신은 이것을 가질 수 있습니다.

vector<N> operator+(const vector<N>& x1, const vector<N>& x2) { vector<N> x3 = x1; x3 += x2; return x3; }
vector<N>&& operator+(const vector<N>& x1, vector<N>&& x2)    { x2 += x1; return std::move(x2); }
vector<N>&& operator+(vector<N>&& x1, const vector<N>& x2)    { x1 += x2; return std::move(x1); }
vector<N>&& operator+(vector<N>&& x1, vector<N>&& x2)         { x1 += x2; return std::move(x1); }

두 매개 변수가 모두 lvalue 인 경우를 제외하고 모든 경우에 복사 (및 가능한 할당)를 방지해야합니다.


아니요. 값만 반환합니다. 일반적으로 참조를 반환하는 것은 전혀 위험하지 않습니다 . 위험한 지역 변수에 대한 참조를 반환 하는 것입니다. 그러나 rvalue 참조를 반환하는 것은 거의 모든 상황에서 꽤 쓸모가 없습니다 (저는 당신이 글을 쓰고 있었다고 생각합니다 std::move).


함수가 종료 된 후 참조 된 객체가 범위를 벗어나지 않을 것이라고 확신하는 경우 참조로 반환 할 수 있습니다 (예 : 전역 객체의 참조 또는 클래스 필드에 대한 참조를 반환하는 멤버 함수 등).

이 반환 참조 규칙은 lvalue 및 rvalue 참조와 동일합니다. 차이점은 반환 된 참조를 사용하는 방법입니다. 내가 볼 수 있듯이 rvalue 참조로 반환하는 것은 드뭅니다. 기능이있는 경우 :

Type&& func();

그런 코드가 마음에 들지 않을 것입니다.

Type&& ref_a = func();

명명 된 rvalue 참조가 lvalue이기 때문에 ref_a를 Type &로 효과적으로 정의하기 때문에 여기에서는 실제 이동이 수행되지 않습니다. 다음과 같습니다.

const Type& ref_a = func();

실제 ref_a가 상수가 아닌 lvalue 참조라는 점을 제외하고.

또한 Type && 인수를 사용하는 다른 함수에 func ()를 직접 전달하더라도 해당 함수 내에서 명명 된 참조이기 때문에 유용하지 않습니다.

void anotherFunc(Type&& t) {
  // t is a named reference
}
anotherFunc(func());

func () 및 anotherFunc ()의 관계는 func ()가 anotherFunc ()가 func ()에서 반환 된 객체의 소유권을 가질 수 있다는 데 동의하는 "권한 부여"와 비슷합니다. 그러나이 합의는 매우 느슨합니다. 상수가 아닌 lvalue 참조는 호출자가 여전히 "도용"할 수 있습니다. 실제로 함수는 rvalue 참조 인수를 사용하도록 정의되지 않습니다. 가장 일반적인 경우는 "anotherFunc"가 클래스 이름이고 anotherFunc ()는 실제로 이동 생성자입니다.


한 가지 더 가능한 경우 : 튜플을 풀고 값을 함수에 전달해야하는 경우입니다.

이 경우 복사 제거에 대해 확실하지 않은 경우 유용 할 수 있습니다.

이러한 예 :

template<typename ... Args>
class store_args{
    public:
        std::tuple<Args...> args;

        template<typename Functor, size_t ... Indices>
        decltype(auto) apply_helper(Functor &&f, std::integer_sequence<size_t, Indices...>&&){
            return std::move(f(std::forward<Args>(std::get<Indices>(args))...));
        }

        template<typename Functor>
        auto apply(Functor &&f){
            return apply_helper(std::move(f), std::make_index_sequence<sizeof...(Args)>{});
        }
};

당신이 어떤 형태의 std::bind또는 std::thread대체물을 작성하지 않는 한 매우 드문 경우 입니다.

참고URL : https://stackoverflow.com/questions/5770253/is-there-any-case-where-a-return-of-a-rvalue-reference-is-useful

반응형