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
대체물을 작성하지 않는 한 매우 드문 경우 입니다.
'Programing' 카테고리의 다른 글
Spring Cloud Eureka Server 자체 보존 및 갱신 임계 값 이해 (0) | 2020.10.25 |
---|---|
ConcurrentDictionary TryRemove는 언제 false를 반환합니까? (0) | 2020.10.25 |
iOS7 UIModalTransitionStyleFlipHorizontal 전환 후 바운스 (0) | 2020.10.25 |
CAShapeLayer 및 UIBezierPath로 부드러운 원을 그리는 방법은 무엇입니까? (0) | 2020.10.25 |
시작시 Tomcat 구성에서 시스템 속성을 어떻게 지정할 수 있습니까? (0) | 2020.10.25 |