2017-05-26 66 views
1

當我運行下面的代碼時,它會生成以下輸出: 第一部分直接使用模板,第二部分使用從模板派生的類。初始化構造
模板假人:初始化構造
模板假人:空構造
模板假人:空構造
模板假人 的移動語義未在派生類(以粗體顯示)如何在從模板類繼承時應用移動語義

模板虛擬調用:+運營商
模板假人:移動分配

模板假人:初始化構造
模板假人:初始化構造
模板假人:空的構造
模板假人:空的構造
模板虛擬:+運營商
模板假人:拷貝構造函數
模板假人:拷貝賦值

我認爲,原因很清楚 - 命名參數會將參數變成左值,因此模板接收一個左值並調用一個拷貝構造函數。

問題是如何在這種情況下強制移動語義?

#include <iostream> 

    using namespace std; 

    template <typename T> class Dummy { 

    public: 

    T val; 

    Dummy& operator=(const Dummy& d){ 
     val = d.val; 
     cout << "Template Dummy: copy assignment\n" ; 
     return *this; 
    } 

    Dummy operator+(const Dummy &d) { 
     Dummy res; 
     res.val = val + d.val; 
     cout << "Template Dummy: + operator\n" ; 
     return res; 
    } 

    // constructors 
    Dummy() { 
     val = 0; 
     cout << "Template Dummy: empty constructor\n" ; 
    } 

    Dummy(const T v) { 
     val = v; 
     cout << "Template Dummy: initializing constructor\n" ; 
    } 

    Dummy(const Dummy &d) { 
     val = d.val; 
     cout << "Template Dummy: copy constructor\n" ; 
    } 

    // move semantics 
    Dummy(const Dummy&& d) { 
     val = d.val; 
     cout << "Template Dummy: move constructor\n" ; 
    } 

    Dummy& operator=(const Dummy&& d){ 
     val = d.val; 
     cout << "Template Dummy: move assignment\n" ; 
     return *this; 
    } 
    }; 

    class FloatDummy : public Dummy<float> { 
    public: 

     FloatDummy& operator=(const FloatDummy& d){ 
     Dummy<float>::operator=(d); 
     return *this; 
     } 

     FloatDummy operator+(const FloatDummy &d) { 
     return (FloatDummy) Dummy<float>::operator+(d); 
     } 

     // constructors 
     FloatDummy() : Dummy<float>() {}; 
     FloatDummy(float v) : Dummy<float>(v) {} 
     FloatDummy(const FloatDummy &d) : Dummy<float>(d) {} 
     FloatDummy(const Dummy<float> &d) : Dummy<float>(d) {} 

     // move semantics 
     FloatDummy(const FloatDummy&& d) : Dummy<float>(d) {} 

     FloatDummy& operator=(const FloatDummy&& d){ 

     // here d is already an lvalue because it was named 
     // thus the template invokes a copy assignment  
     Dummy<float>::operator=(d); 
     return *this; 
    } 
    }; 

    int main() { 
    Dummy<float> a(1), b(1); 
    Dummy<float> c; 
    c = a + b; 
    cout << c.val << '\n';; 

    FloatDummy d(1), e(1); 
    FloatDummy f; 
    f = d + e; 
    cout << f.val << '\n'; 
    } 
+0

刪除'const'從常量的'所有情況下&&',並使用'的std ::移動(d )'從'd'移動 –

回答

2

你不能從const&移動。要解決,只是從你所有的移動操作刪除const

FloatDummy(FloatDummy&& d) : Dummy<float>(d) {} 
//   ^^^^^^^^^^^^ no longer FloatDummy const&& 

FloatDummy& operator=(FloatDummy&& d) { /*...*/ } 
//     ^^^^^^^^^^^^ ditto 

運動的本質是取得所有權的資源,你怎麼能採取的所有權的東西,如果你不能修改源?因此,默認情況下,移動操作不適用於const類型。

你會想要爲Dummy類做同樣的事情。


需要調用std::move()d到右值參考:儘管d的參數類型是右值引用,函數本身d裏面是相當多認爲是左值參考。這意味着當你將它傳遞給實際使用它的任何東西時,仍然需要將它轉換爲右值引用(整個點爲std::move())。

在你的情況,這是正確的,當你把它傳遞給Dummy<float>的構造函數或Dummy<float>::operator=

FloatDummy(FloatDummy&& d) : Dummy<float>(std::move(d)) {} 
//          ^^^^^^^^^ calling std::move() 
//             otherwise copy ctor overload is chosen 

FloatDummy& operator=(FloatDummy&& d) 
{ 
    Dummy<float>::operator=(std::move(d)); 
    //      ^^^^^^^^^ ditto 
    return *this; 
} 
+0

這解決了這個問題。我也有一個錯過的移動構造函數,它沒有從模板中複製而導致複製。現在我有一個**移動**構造函數和一個**移動**任務。 謝謝! – PolarBear2015