2016-07-16 39 views
1
class MyClass { 
    public: 
     MyClass() 
     { 
      std::cout << "default constructor\n"; 
     } 
     MyClass(MyClass& a) 
     { 
      std::cout << "copy constructor\n"; 
     } 

     MyClass(MyClass&& b) 
     { 
      std::cout << "move constructor\n"; 
     } 
}; 

void test(MyClass&& temp) 
{ 
    MyClass a(MyClass{}); // calls MOVE constructor as expected 
    MyClass b(temp); // calls COPY constructor... not expected...? 
} 

int main() 
{ 
    test(MyClass{}); 
    return 0; 
} 

對於上面的代碼中,我預期無論在測試對象創建()來調用移動的構造,因爲b是右值引用類型(MyClass的& &)。c + +移動的構造不要求右值參考

但是,將b傳遞給MyClasss構造函數並不像預期的那樣調用移動構造函數,而是調用複製構造函數。

爲什麼第二個案例調用拷貝構造函數,即使傳入的參數是MyClass類型& &(r值參考)???

我使用的是gcc 5.2.1。要重現我的結果,您必須將-fno-elide-constructors選項傳遞給gcc以禁用副本優化。


void test(MyClass&& temp) 
{ 
    if (std::is_rvalue_reference<decltype(temp)>::value) 
     std::cout << "temp is rvalue reference!!\n"; 
    else 
     std::cout << "temp is NOT rvalue!!\n"; 
} 

上面的代碼打印出「溫度是右值引用」,即使溫度而得名。

temp的類型是右值引用類型。

+0

表達'temp'計算結果爲左值refernce,而不是右值引用。你將'temp'聲明爲右值引用並不重要。一個*名爲*的引用永遠是一個左值。 – AnT

+0

@AnT你在C++標準文檔中有任何參考嗎?我非常努力地尋找這條規則的任何參考,但我找不到一個...... – SHH

+2

請參閱** 5表達式**的開頭。全部在5/5,5/6和5/7。特別參見注5/7,它基本上是這樣描述的。此外,鏈接的「重複」鏈接到一個托馬斯貝克爾關於這個話題的文章。 – AnT

回答

3
void test(MyClass&& temp) 
{ 
    MyClass a(MyClass{}); // calls MOVE constructor as expected 
    MyClass b(temp); // calls COPY constructor... not expected...? 
} 

這是因爲,temp(因爲它有一個名字,)是lvalue參照一個rvalue。爲了治療爲rvalue在任何時候,呼籲std::move

void test(MyClass&& temp) 
{ 
    MyClass a(MyClass{}); // calls MOVE constructor as expected 
    MyClass b(std::move(temp)); // calls MOVE constructor... :-) 
} 
+0

'一個左值的左值引用'...右值如何具有左值引用?這超出了我的理解。 – Youda008