右值参考和设置功能

时间:2015-09-25 15:19:12

标签: c++ c++11 move-semantics

我想在main()函数中创建类实例时使用便捷函数来使事情更清晰。

这是一个最小的例子:

class MyClass
{
    public:
            MyClass() : value{ -1 }, str{ "hello" } {}
            MyClass( const MyClass &&other )
            {
                    value = move( other.value );
                    str = move( other.str );
                    file = move( other.file ); //Use of deleted function...
            }

            void open()
            {
                    file.open( "myfile" );
            }

    private:
            MyClass( const MyClass & ) = delete;
            MyClass operator=( const MyClass & ) = delete;
            MyClass &operator=( const MyClass && ) = delete;

            ofstream file;
            int value;
            string str;
};

inline MyClass setup_myclass()
{
    MyClass ret;
    ret.open();

    return ret;
}

int main( int argc, char **argv )
{
    MyClass &&mc = setup_myclass();

    return 0;
}

问题是当我的类包含像fstream或线程那样删除了移动构造函数的东西时。

我正在使用g ++ 5.1.1和arm-linux-g ++ 5.2.0(raspberrypi,buildroot)进行编译。

当我有成员删除移动构造函数时,我的移动构造函数应该是什么样的?

如何更改代码以使其具有相同的干净主函数?

1 个答案:

答案 0 :(得分:4)

这里有两个问题。首先,您的移动构造函数具有错误的签名:

MyClass( const MyClass &&other )

您无法从const左值移动。你的意思是:

MyClass( MyClass &&other )

而且更重要的是,你的意思是:

MyClass( MyClass &&other ) = default;

Rule of Zero。你的所有成员都有移动构造函数(std::threadstd::ofstream!),所以只需使用它们。同样,这个:

MyClass &operator=( const MyClass && ) = delete;

应为public,如下所示:

MyClass &operator=( MyClass && ) = default;

为什么要启用移动构造函数,但delete移动赋值?

其次,这很糟糕:

MyClass &&mc = setup_myclass();

你刚刚引用了一个在行尾被破坏的临时文件。你现在有一个悬空参考。你想做的只是:

MyClass mc = setup_myclass();

感谢RVO,实际上不会在此处调用此举。 setup_myclass()内的临时内容实际上将在mc内就地构建。