4

我一直有困難在C++中理解移動構造函數。我用默認構造函數,複製構造函數,移動構造函數和析構函數做了一個簡單的類。另外,我定義了一個帶有兩個重載的函數,一個接受對該類的引用,另一個接受對該類的右值引用。我的測試代碼如下。與移動構造函數混淆:無法調用移動構造函數

#include <iostream> 


class c { 

public: 

    c() { 
     std::cout << "default constructor" << std::endl; 
    } 

    c(const c& s) { 
     std::cout << "copy constructor" << std::endl; 
    } 

    c(c&& s) { 
     std::cout << "move constructor" << std::endl; 
    } 

    ~c() { 
     std::cout << "destructor" << std::endl; 
    } 

}; 

void f(c& s) { 
    std::cout << "passed by reference" << std::endl; 
} 

void f(c&& s) { 
    std::cout << "passed by rvalue reference" << std::endl; 
} 

int main() { 

    c s1; // line 1 
    std::cout << "\n"; 
    c s2(s1); // line 2 
    std::cout << "\n"; 
    c s3(c()); // line 3 

    std::cout << "\n"; 

    f(s1); // line 4 
    std::cout << "\n"; 
    f(c()); // line 5 

    getchar(); 
    return 0; 

} 

我得到的輸出不是我期待的。以下是我從這段代碼中得到的輸出。

default constructor 

copy constructor 

passed by reference 

default constructor 
passed by rvalue reference 
destructor 

我可以理解除line 3之外的所有行的輸出。在line 3,這是c s3(c());,c()是一個右值,所以我認爲s3將移動構建。但是輸出結果並不表明它是構建的。在line 5上,我正在做同樣的事情並將rvalue傳遞給函數f(),它確實調用接受rvalue引用的過載。我很困惑,並希望有關於此的任何信息。

編輯:我可以調用移動構造函數,如果我c s3(std::move(c()));但我沒有傳遞一個右值到s3?爲什麼我需要std::move

+2

@NathanOliver這不是真的這一塊的副本。這裏發生的事情是最痛苦的解析,而不是複製elision。 – Angew

+0

@Angew好的電話。錯過了。 – NathanOliver

+0

@Angew我實際上想要做的是通過它的移動構造函數構造一個對象,當NathanOliver指示我去處理另一個問題時,我真的認爲這是重複的。我甚至沒有注意到第3行的聲明是一個函數簽名,直到您指出。我從來沒有聽說過最棘手的解析,所以謝謝你與我分享;我會閱讀它來了解它是什麼。 – Deniz

回答

9

您看不到第3行的任何輸出的原因是它聲明瞭一個函數,而不是一個變量。這是由於被稱爲Most Vexing Parse的含糊不清造成的。

c s3(c())int foo(int())進行比較,這歸功於隱式類型調整,與int foo(int (*f)())相同。

爲了解決這個問題,用大括號初始化(這實際上是在C++ 11引入了部分因爲這個原因):

c s3(c{}); 

// or 

c s3{c()}; 

// or 

c s3{c{}}; 
+0

謝謝您提供的信息豐富的答案。這和M.M的答案都回答了我的問題。然而,顯然你比他們早了一分鐘,所以我會接受你的答案。感謝你和M.M爲你的時間和幫助。 – Deniz

5

c s3(c());不構建任何對象。這是一個函數聲明。該函數被稱爲s3,返回類型是c,參數類型是「函數指針不帶參數並返回c」。所以你沒有輸出,因爲函數聲明不會調用任何函數。

爲了避免這種情況,您可以使用列表初始化,c s3{c()};可能更符合您的想法。

+0

+1 for info'參數類型是「指向不帶參數並返回c」的函數的指針。如果它是'c(x)',那麼參數類型是'c'並且名稱是'x' –