2017-05-26 34 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