2014-07-17 8 views
2

은 내가 그들에게 CONST (가 복사 될 것이다) 좌변과 (속도)를 rvalue 참조C++은 함수에 const를 좌변과를 rvalue 참조를 가지고

struct Object { 
    ... 
    Object(Object&& o) { ... } 
    Object(const Object& o) { ... } 
    ... 
}; 

... 

struct SomeClass { 
    ... 
    Object arr[7]; 

    void copy(int pos,const Object& o) { arr[pos] = o; } 
    void copy(int pos,Object&& o) { arr[pos] = o; } 
    ... 
}; 
에 의해 변수를 취할 수있는 능력을 제공해야 할 몇 가지 방법이

따라서 SomeClass에서는 두 가지 복사 방법이 완벽하게 동일합니다. 유일한 차이점은 하나의 Object가 복사 될 const로 전달되고 다른 Object는 rvalue 참조로 빠른 복사를 위해 소비되도록 전달된다는 것입니다.

이 두 코드의 코드는 완전 동일합니다.

이제 위의 예에서 비극적 인 것은 아니지만 조금 더 큰 9-15 줄 정도의 방법이 있습니다. 해결 방법은 분명히 여기에서했던 것처럼 복사하는 것입니다.하지만 옳다고 생각하지는 않습니다.

복사 방법 코드는 어떻게 재사용 할 수 있습니까?

+3

값을 인수로 취하고 함수 내에서'std :: move'를 취할 수 있습니다. – Praetorian

+0

음, Object 클래스는 rvalue 참조 생성자를 사용하여 객체의 멤버 변수를 "훔치거나"지정된 객체에 아무 것도 남겨 두지 않습니다. const Object 생성자는 객체를 수정할 수 없으며 변수를 훔칠 수도 없으므로 복사해야합니다. –

+0

@Praetorian 그건 좋은 생각이야. 나는 아무것도 복사하지 않고 다른 방법을 찾지 못하면 아마 그것을 사용할 것이다. –

답변

2

전체 참조 및 std::forward을 사용하면 완벽한 전달을 구현할 수 있습니다. 여기에 copy 수정 : 당신이 Object 다른 유형의 가능한 암시 적 변환에 대해 걱정하는 경우

template <typename T> 
void copy(int pos, T&& o) {arr[pos] = std::forward<T>(o);} 

, 당신은 또한 copy의 몸에 static_assert를 추가 할 수 있습니다. l 값 Objectcopy에 전달하면 TObject&으로 추론됩니다. std::forward<Object&>은 참조를 반환합니다. 따라서 복사 할당 과부하가 선택됩니다. r 값 Objectcopy에 전달하면 TObject으로 추론됩니다. std::forward<Object&>Object&&을 반환합니다. std::forward<Object>(o)도 역시 rvalue이므로 이동 할당 연산자가 선택됩니다.

+0

완료! 나는 다른 최고의 대답을하고 당신에게 그것을주는 것을 슬프다. ( –

3

첫째, 당신은 두 경우 모두 복사 할당을하고있다 : 그것은 이름이있는 경우

void copy(int pos,const Object& o) { arr[pos] = o; } 
void copy(int pos,Object&& o) { arr[pos] = o; } 

는, 그것은 좌변입니다. 두 번째 함수에서 o은 이름을 가지므로 우변 값입니다 (rvalue 참조 임에도 불구하고). 너는 arr[pos] = std::move(o);을 원한다. arr[pos]에 할당으로 이동 다음은 좌변을 전달하면

void copy(int pos, Object o) { arr[pos] = std::move(o); } 

o가 건설 복사되고, :

두 번 copy를 작성하지 않도록하는 일반적인 방법은 값으로 o을하고 그것에서 이동하는 것입니다 . rvalue를 전달하면 o이 이동되고 배열로 더 이동됩니다. 그럼에도 불구하고 평범한 경우에는 복사본을 피할 수 있지만 두 경우 모두 추가 이동 비용을 지불해야합니다. 그들이해야하는 것처럼 움직임이 싸다면 많은 여분의 오버 헤드가 없습니다.

그러나이 기능은 이동 의미 체계를 지원하지 않는 레거시 형식에서는 제대로 작동하지 않습니다. 이 경우이 함수는 전달한 내용의 사본을 만들어 사본에서 할당하고 참조를 가져 오는 두 개의 오버로드는 하나의 사본 만 수행합니다.

+0

그럼,이 둘을이 것으로 대체 하시겠습니까? 그러나 SomeClass의 사용자가 copy를 호출 할 때 std :: move를 혼자서 사용하고 싶다면 어떻게해야할까요? sc.copy (0, std :: move (tempobj)); 아니면 제대로 이해하지 못했습니까? –

+0

오, 알았어,이 변종으로 2 배의 평범한 가치가 생겼어. 나는 그것을 좋아한다! –

+0

@VanillaFace'std :: move'와 같은 rvalue를 전달하면 'o'가 이동되어 배열로 옮겨집니다. –