2017-01-28 60 views
-2
Foo(Foo&& other) { 
    this->bar = other.bar; 
    other.bar = nullptr; 
} 

Foo(Foo* other) { 
    this->bar = other->bar; 
    other->bar = nullptr; 
} 

以上兩個似乎只是在做同樣的事情。那麼爲什麼建議使用移動構造函數呢?它提供了什麼優勢?使用移動構造函數與傳遞指針有什麼優勢?

+2

那麼,對於初學者來說,你不能採用右值的地址...... – Brian

+2

優點是移動構造函數將在適用的移動/複製上下文中自動使用。你的「指針」構造函數不會。 – AnT

+0

另外,引用不能爲空,但可以是一個指針,所以在交換之前你必須顯式檢查這個條件。 –

回答

4

使用適當的轉移構造的原因有很多:

  1. 公約。請看下面的代碼:

    Foo foo; 
    Foo bar(std::move(foo)); 
    

    如果你看到代碼,它是豐富清楚你想要做什麼:你正在移動foobar。相比之下:

    Foo foo; 
    Foo bar(&foo); 
    

    這是什麼意思?它是否存儲指向另一個Foo的指針?是Foo某種鏈接列表節點類型?您必須在Foo的基於指針的構造函數的文檔中查找它。

  2. 你不能得到一個指向prvalues的指針。 (pre-C++ 17)會創建一個臨時值,然後從它移動到bar(此舉可能會在C++ 17之前被忽略)。但是你不能這樣做:Foo bar(&Foo{})

  3. 你可以從有意義的事物中自動移動。 C++ 17的廣義省音讓許多的這些舉動自動消失,但也有一些仍然存在:

    Foo function() 
    { 
        Foo foo; 
        //Do stuff 
        return foo; 
    } 
    

    這將從foo移動,而無需調用std::move。原因是foo是即將銷燬的局部變量。以這種方式返回意味着從它轉換到返回值是完全合理的。

    你的方式需要明確寫入return &foo。這使得返回類型扣除auto變得相當困難。這樣的函數會推導出一個Foo*,這意味着你剛剛返回了一個懸掛指針。而如果你做return foo;,它會推導一個Foo prvalue,並帶有一個自動移動(可能會被忽略)。

  4. 無需nullptr檢查。如果你拿一個Foo*,有人可能會傳遞一個空指針。而引用,這是不太可能的(他們已經調用UB)。

如果我們想移動與現有的語言結構的支持,我們會剛使用非const引用意味着「移動」,而不是一個指針。通過賦予它自己的語法,在我們移動某個事物時以及當我們不移動時清楚地說明。

相關問題