我想在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)进行编译。
当我有成员删除移动构造函数时,我的移动构造函数应该是什么样的?
如何更改代码以使其具有相同的干净主函数?
答案 0 :(得分:4)
这里有两个问题。首先,您的移动构造函数具有错误的签名:
MyClass( const MyClass &&other )
您无法从const
左值移动。你的意思是:
MyClass( MyClass &&other )
而且更重要的是,你的意思是:
MyClass( MyClass &&other ) = default;
见Rule of Zero。你的所有成员都有移动构造函数(std::thread
和std::ofstream
!),所以只需使用它们。同样,这个:
MyClass &operator=( const MyClass && ) = delete;
应为public
,如下所示:
MyClass &operator=( MyClass && ) = default;
为什么要启用移动构造函数,但delete
移动赋值?
其次,这很糟糕:
MyClass &&mc = setup_myclass();
你刚刚引用了一个在行尾被破坏的临时文件。你现在有一个悬空参考。你想做的只是:
MyClass mc = setup_myclass();
感谢RVO,实际上不会在此处调用此举。 setup_myclass()
内的临时内容实际上将在mc
内就地构建。