簡體   English   中英

為什么要使用move構造函數?

[英]why use a move constructor?

對於您為什么要使用/需要移動構造函數,我有些困惑。
如果我有以下內容:

vector fill(istream& is)
{
    vector res;
    for(double x; is >> x; res.push_back(x));
    return res;
}

void bar()
{
    vector vec = fill(cin);
    // ... use vec ...
}

我可以通過添加vector fill(istream& is, vector& res)來消除返回res的需要,因此不必調用copy構造函數。

那么擁有move構造函數有什么意義呢?

假設您接下來將std::vector<T>放入std::vector<std::vector<T>> (如果您認為向量不應該嵌套,則假定內部類型為std::string並假設我們正在討論std::string的move構造函數):即使您可以添加一個空對象並就地填充它,最終向量也需要在調整大小時重新定位,這時移動元素便會派上用場。

請注意,從函數返回並不是移動構造的主要動力,至少不是在效率方面:在效率很重要的情況下,結構化代碼以啟用復制刪除功能甚至可以通過避免移動來進一步提高性能。

但是,由於在返回時要求類型是可復制的或可移動的,因此move構造函數在語義上仍可能是相關的。 某些類型(例如流)是不可復制的,但它們是可移動的,可以通過這種方式返回。

在您的示例中,編譯器可能會應用RVO-返回值優化,這意味着您將內聯函數,因此不會發生返回-並且不會應用移動語義。 僅當它不能應用RVO時,將使用move構造函數(如果可用)。

在引入移動語義之前,人們使用各種技術來模擬它們。 其中之一實際上是通過引用返回值。

原因之一是使用賦值運算符可以更輕松地掌握每行的內容。 如果有一個調用somefunction(var1, var2, var3)的函數,則不清楚其中是否有人被修改。 為了找出答案,您必須實際閱讀其他功能。

另外,如果必須將向量作為參數傳遞給fill() ,則意味着調用函數的每個位置都將需要兩行而不是一行:首先創建一個空向量,然后調用fill()

另一個原因是,移動構造函數允許函數返回沒有默認構造函數的類的實例。 考慮以下示例:

struct something{
    something(int i) : value(i) {}
    something(const something& a) : value(a.value) {}

    int value;
};

something function1(){
    return something(1);
}

void function2(something& other){
    other.value = 2;
}

int main(void){
    // valid usage
    something var1(18);
    // (do something with var1 and then re-use the variable)
    var1 = function1();

    // compile error
    something var2;
    function2(var2);
}

如果您擔心效率問題,那么無論您編寫fill()返回值還是將輸出變量作為參數,都無關緊要。 您的編譯器應將其優化為這兩個中最有效的替代方案。 如果您懷疑不是,則最好對其進行度量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM