2017-10-04 90 views
3

考慮以下示例代碼初始化:C++ 11單元素矢量在一個函數調用

實施例:

void print(int n) { 
    cout << "element print\n"; 
} 

void print(vector<int> vec) { 
    cout << "vector print\n"; 
} 

int main() { 
    /* call 1 */ print(2); 
    /* call 2 */ print({2}); 
    std::vector<int> v = {2}; 
    /* call 3 */ print(v); 
    /* call 4 */ print(std::vector<int>{2}); 
    return 0; 
} 

產生以下輸出:

element print 
element print 
vector print 
vector print 

爲什麼調用print函數(在上面的例子中調用2)正在匹配函數接受單個值?我在這個調用中創建了一個向量(包含一個元素),所以如果它不匹配以向量作爲輸入調用print

這是部分討論的in an other question其中提供的解決方案適用於具有多個元素的向量。

回答

6

因爲在過載分辨率print({2});所述第一過載勝。

在這兩種情況下copy list initialization適用,爲第1過載服用int

(重點煤礦)

否則(如果T不是類類型),如果支撐-初始化列表只有一個元素,並且T不是引用類型或者是與元素類型兼容的引用類型,所以T被直接初始化(在直接列表初始化中)或者拷貝初始化(在拷貝中)列表初始化),exce pt縮小轉換是不允許的。

{2}只有一個元素,它可以用來直接初始化一個int作爲參數;這完全匹配。

對於第二超載服用std::vector<int>

否則,T的構造都認爲,在兩個階段:

  • 所有構造函數取std::initializer_list作爲唯一的參數,或者作爲第一參數,如果其餘參數具有默認值,則檢查並通過重載分辨率與類型的單個參數進行匹配std::initializer_list

這意味着一個std::initializer_list<int>被構造並用作構造函數的參數std::vector<int>(構造參數爲print)。一個用戶定義的轉換(通過構造函數std::vector取一個std::initializer_list)是必需的,那麼它的匹配比第一個重載更差。

8

{2}是許多類型的合法初始值設定項,包括int。重載解析更喜歡與需要進一步構造的類型完全匹配的類型。

2

不,你不是在創建一個initializer_list。

參見:http://en.cppreference.com/w/cpp/utility/initializer_list

呼叫1)單元被稱爲

呼叫2)initializer_list創建單個int元件

呼叫3)矢量對象是以給定的

呼叫4)一個Vector對象被給出

Overload resulotion傾向於在std :: vector之前使用int參數方法參數方法,因爲有更少的類型轉換。 int參數是直接匹配,對於vector參數需要額外的轉換。

例如:

void print(std::initializer_list<int> list){ 
    cout << "initializer_list print\n"; 
} 

將導致用於呼叫2,即輸出爲「initializer_list打印」

+1

重要提示:支撐初始化器列表是*無類型*,而不是'std :: initializer_list'。所以你的第一句話是錯誤的。 – Rakete1111