2016-11-12 36 views
3
#include <iostream> 
#include <string> 

void fnc (const std::string&) 
{ 
    std::cout<<1; 
} 

void fnc (std::string&&) 
{ 
    std::cout<<2; 
} 

int main() 
{ 
    fnc ("abc"); 
} 

所有的編譯器選擇std::string&&版本的fnc,這是合乎邏輯的,因爲臨時std::string爲參考結合創建的,但我找不到,它在哪裏描述在C++ 14標準中。 我發現有一個段(3.2):重載決策

- 標準轉換序列S1比 標準轉換序列S2更好的轉換序列如果

[...]

- S1和S2是參考綁定(8.5.3),並且都不參考 非靜態成員函數的隱式對象參數,其被聲明爲 而沒有ref限定符,並且S1將右值引用綁定到右值 和S2結合左值參考

但它不是這種情況下,因爲S1結合一個rvalue參照一個左值(「ABC」,左值常量字符的[4])。 我在哪裏可以找到描述,選擇第二個過載?

P.S.我指向C++ 14標準而不是C++ 11,因爲我知道,在C++ 11中有一些缺陷報告與rvalue引用綁定關聯。

回答

6

首先編譯器爲​​執行隱式數組到指針轉換,因此​​的類型變爲const char*。其次(你可能錯過了),const char*通過const char*non-explicit constructor of std::string(鏈接#5)轉換爲右值std::string。構造的std::string右值與第二次過載完美匹配,因此選擇第二次過載。

+3

這是一個數組到指針的轉換,而不是l到r。 –

+0

@ T.C。是的,你是對的,糾正。 – vsoftco

1

但事實並非如此,因爲S1將左值引用綁定到左值(「abc」,const char [4]的左值)。

請注意,​​是const char[4],而不是std::string。但fnc()都以std::string爲參數,引用不能直接綁定到不同類型的對象。因此,首先需要將​​隱含地轉換爲std::string,這是臨時的,即的右值。然後如標準所示,右值參考超載將被選中。

1

​​不能直接傳入任何超載的fnc()。對於他們兩個,它必須轉換爲(右值)std::string。但是,標準中引用的規則明確地選擇了fnc(std::string&&)而不是fnc(const std::string&)