2013-03-12 4 views
13

이동 생성자 및 할당 연산이 C++ 11에서 작동하는 방식을 이해하려고하는데 부모 클래스에 위임하는 데 문제가 있습니다.생성자 및 상속 이동

코드 : 그러나

class T0 
{ 
public: 
    T0() { puts("ctor 0"); } 
    ~T0() { puts("dtor 0"); } 
    T0(T0 const&) { puts("copy 0"); } 
    T0(T0&&) { puts("move 0"); } 
    T0& operator=(T0 const&) { puts("assign 0"); return *this; } 
    T0& operator=(T0&&) { puts("move assign 0"); return *this; } 
}; 

class T : public T0 
{ 
public: 
    T(): T0() { puts("ctor"); } 
    ~T() { puts("dtor"); } 
    T(T const& o): T0(o) { puts("copy"); } 
    T(T&& o): T0(o) { puts("move"); } 
    T& operator=(T const& o) { puts("assign"); return static_cast<T&>(T0::operator=(o)); } 
    T& operator=(T&& o) { puts("move assign"); return static_cast<T&>(T0::operator=(o)); } 
}; 

int main() 
{ 
    T t = std::move(T()); 
    return 0; 
} 

, 내가 컴파일하고 VS2012에서 실행, 출력은 T0 회원의 좌변 버전이라고 나타냅니다

ctor 0 
ctor 
copy 0 <-- 
move <-- 
dtor 
dtor 0 
dtor 
dtor 0 

유사한 상황을 (함께 약간 다른 테스트 케이스)는 이동 할당에서 발생합니다. T의 이동 할당 연산자는 T0의 "일반"할당 연산자를 호출합니다.

내가 뭘 잘못하고 있니?

답변

16

하나 rvalue 참조를 매개 변수로 사용하는 함수에 대해 혼란스러운 점은 내부적으로 매개 변수를 lvalues로 처리한다는 것입니다. 이는 매개 변수를 옮기기 전에 매개 변수를 이동하지 못하도록하는 것이지만 익숙해지는 데 걸리는 시간입니다. 실제로 매개 변수를 이동하려면 std :: move (또는 std :: forward)를 호출해야합니다. 그래서 당신은 당신의 이동 생성자를 정의 할 필요가로 :

T(T&& o): T0(std::move(o)) { puts("move"); } 

와 같은 이동 할당 연산자 :

T& operator=(T&& o) { puts("move assign"); return static_cast<T&>(T0::operator=(std::move(o))); } 
5

당신은 오직 lvalues으로 기본 클래스의 물건을 호출하고 있습니다 :입니다

void foo(int&){} // A 
void foo(int&&){} // B 

void example(int&& x) 
{ 
    // while the caller had to use an rvalue expression to pass a value for x, 
    // since x now has a name in here it's an lvalue: 
    foo(x); // calls variant A 
} 

example(std::move(myinteger)); // rvalue for us, lvalue for example 

, 당신이 필요합니다

T(T&& o): 
T0(std::move(o)) // rvalue derived converts to rvalue base 
{ 
    puts("move"); 
} 

그리고 : 더의

T& operator=(T&& o) 
{ 
    puts("move assign"); 

    T0::operator=(std::move(o))); 

    return *this; 
}