2017-04-09 106 views
2

考慮下面的代碼爲什麼調用轉發引用構造函數而不是複製構造函數?

#include <iostream> 

using namespace std; 

template <typename Type> 
struct Something { 
    Something() { 
     cout << "Something()" << endl; 
    } 

    template <typename SomethingType> 
    Something(SomethingType&&) { 
     cout << "Something(SomethingType&&)" << endl; 
    } 
}; 

int main() { 
    Something<int> something_else{Something<int>{}}; 
    auto something = Something<int>{}; 
    Something<int>{something}; 
    return 0; 
} 

我得到以下輸出

Something() 
Something() 
Something(SomethingType&&) 

爲什麼拷貝構造函數解析成模板轉發參考構造函數,但不是移動構造函數?我猜測這是因爲移動構造函數是隱式定義的,而不是複製構造函數。但是在閱讀堆棧溢出中未隱式定義拷貝構造函數的情況後,我仍然感到困惑。

+1

這是一個體面的共同話題博客:https://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/ – chris

回答

4

我猜測這是因爲移動構造函數是隱式定義的,而不是複製構造函數。

不,這兩者都是爲Something類別隱式定義的。

,就是因爲拷貝構造函數採用const Something&作爲其參數拷貝構造函數解析成模板轉發參考構造

。這意味着要調用複製構造函數,需要隱式轉換才能添加const限定符。但是轉發參考構造函數可以被實例化採取Something&作爲它的參數,那麼它的精確匹配,勝在重載決議。

因此,如果您製作somethingconst,則將針對第三種情況而不是轉發引用構造函數調用隱式定義的複製構造函數。

LIVE

而不是移動構造函數?

因爲對於移動構造函數上述問題並不重要。對於第一種和第二種情況的調用,隱式定義的移動構造函數和轉發引用構造函數是完全匹配的,然後非模板移動構造函數獲勝。

+3

一本書,我瞭解這些類型的問題,發現是非常有益的[ Effective Modern C++](http://shop.oreilly.com/product/0636920033707.do)作者:Scott Meyers。 –