2015-09-25 73 views
-1

我想在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

'std :: ofstream'有一個移動構造函數。 [這是複製構造函數被刪除](http://en.cppreference.com/w/cpp/io/basic_ofstream/basic_ofstream) – NathanOliver

+1

錯誤的物質。 std :: ofstream和std :: thread都有移動構造函數。你爲什麼認爲你在那裏有問題?提供編譯器消息。 – SergeyA

+0

將'MyClass(const MyClass && other)'改成'MyClass(MyClass && other)' –

回答

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中就地構建。

+1

*「你只是引用了一個在行末被銷燬的臨時對象。」*,不會直接綁定臨時對象右值引用是否延長了該臨時的生命週期? –

+1

@PiotrSkotnicki沒有。 「函數返回語句(6.6.3)中臨時綁定到返回值的生命週期不是 擴展;在返回語句的完整表達式末尾,臨時數據被銷燬。「 – Barry

+1

這是一個令人驚訝的和有點令人驚訝的(但不是真正的)引用擴展例外,我_always_忘記了它 –