2013-05-17 3 views
9

다음 코드에서 std :: move가 아무런 효과가 없거나 완전히 잘못되었는지 파악할 수 없습니까? 클래스 Object에는 이동 및 복사 생성자가 모두 정의되어 있습니다. 여기std :: move는 effeciency에 대한 return 문에 사용해야합니까?

template<typename T> template<typename F> 
Object<T>& Object<T>::operator*=(const F& rhs) 
{ 
    for(int i = 0; i < dimension ; i++) 
    { 
     _inner[i] *= rhs; 
    } 
    return *this; 
} 

는 공동이다

첫째

template<typename T> template <typename F> 
const Object<T> Object<T>::operator*(const F& rhs) const 
{ 
    return std::move(Object(*this) *= rhs); // We end in move constructor 
} 

번째 : 이동없이 : 이동과 마찬가지로

template<typename T> template <typename F> 
const Object<T> Object<T>::operator*(const F& rhs) const 
{ 
    return Object(*this) *= rhs; // We end in copy constructor 
} 

*= 오퍼레이터 정의 드 그것을 테스트하는 데 사용

Object<double> test(4); 
Object<double> test2(test * 4); 
std::cout << test2; // works fine 

결과 우리가 이동 생성자 단부 경우와 우리가 복사 생성자에서 끝난다.

두 경우 모두 코드가 컴파일됩니다.

새로운 개체를 복사하는 대신 밖으로 이동하는 것이 더 빠르다고 가정하기 때문에 다른 하나보다 효율적입니까?

추가 정보 : 나는 다음과 같은 컴파일러를 사용 : 나는 가정 것이기 때문에 g ++ (우분투/리나 4.7.3-1ubuntu1는) 4.7.3

+7

'const' 값을 반환하지 않고 명시 적으로'std :: move' 로컬 변수/임시 변수를 지정하지 않으면 (N) RVO를 금지합니다. 왜 당신의'operator * '를'Object tmp (* this);라고 쓰지 않을까요? tmp * = rhs; return tmp;'? 그런 식으로 컴파일러는 지역 변수를 반환하고 그것을 반환 할 때 자동으로 rvalue로 변환합니다. – Xeo

+0

다음을보십시오 : http://stackoverflow.com/questions/4986673/c11-rvalues-and-move-semantics-confusion – Steve

+0

방금'const'없이 테스트했는데 상황은 변하지 않았지만 이해할 수있었습니다. 내가'std :: move'가 필요로하는 답에서'lvalue'를 반환합니다. 반면에'rvalue'라면'std :: move'가 필요 없습니다. 마지막으로 임시 변수를 사용하면 자동으로 이동됩니다. – CodeTower

답변

14

이 다른 쪽보다 더 효율적입니다 새로운 객체를 복사하는 대신 빠르게 옮길 수 있습니까?

예, std::move을 사용하면 오브젝트가 복사보다 이동이 더 효율적이라고 가정 할 때 여기에서보다 효율적입니다.

일반적으로 임시 또는 로컬 변수를 반환하면 이동 의미가 자동으로 사용됩니다. 그러나이 경우 일시적으로 직접 반환하지는 않지만 왼쪽 값 참조는 operator*=으로 반환됩니다. 왼쪽의 값은 이동하지 않으므로이 경우 std::move이 필요합니다. 의 값인으로 변경해야합니다.

그러나 const 값을 반환하면 반환 값이 다른 개체를 이동 초기화 (또는 이동 할당)하는 데 사용되지 않으므로 값을 반환하지 않아야합니다. 귀하의 예제는 test2으로 복사하고을 복사 할 수 있지만 반환 값은 생략 할 수 있습니다.

또는 로컬 변수를 사용하여 구현할 수 :

template<typename T> template <typename F> 
Object<T> Object<T>::operator*(const F& rhs) const 
{ 
    Object lhs(*this); 
    lhs *= rhs; 
    return lhs; 
} 

뿐만 아니라이 반환 값은 이동 될 수 있지만, 이동 자체가 생략 될 수있다.

+0

나는 RVO가 lvalue 케이스를 돌보아 의심 할 여지가 없어야한다고 생각한다. (아마도 RVO가 움직이는 것에 약간의 이점이있다). 그러나 마지막 예제 (지역 변수)는 어쨌든 모든 것을 해결합니다. +1 – syam

+1

@syam : 저는 (직접) 임시 또는 로컬 자동 변수를 반환 할 때만 elision을 사용할 수 있다고 확신합니다. 필자의 컴파일러는 * lvalue *를 반환 할 때 복사본을 삭제하지 않습니다. –

+0

또한'auto c = a * b; '와 같이 사용되는 경우 반환 값이 복사가 아닌 *const' *'Object '을 반환하도록 조언하십시오 – Xeo

관련 문제