2016-12-14 50 views
2

我必須誤解如何auto C++ 11和更高版本解析類型。我有以下代碼:C++ 11從算術運算的自動類型扣除int&和long

void foo(int& x) 
{ 
    ++x; 
} 

int main() 
{ 
    int i = 2; 
    int& ir = i; 
    long L = 5; 
    auto a = ir/L; 
    foo(a); 

    return 0; 
} 

這將導致編譯器錯誤:

test.cpp: In function 'int main()': 

test.cpp:12:10: error: invalid initialization of non-const reference 
of type ‘int&’ from an rvalue of type ‘int’ 
    foo(a); 
     ^

test.cpp:1:6: note: initializing argument 1 of ‘void foo(int&)’ 
void foo(int& x) 
     ^~~ 

然而,隨着intint a = ir/L;)編譯罰款代替auto並給出了預期的結果(a == 0調用foo()前,以及之後的a == 1)。在玩完代碼並看到各種錯誤消息之後,我認爲auto推導爲long int&。定義函數void bar(int x)void bar(const int& x)會導致錯誤消息:call of overloaded ‘bar(long int&)’ is ambiguous。從評論

更正:

我不明白怎麼auto x = [int&]/[int]結果,可以通過非const裁判被傳遞的左值,而auto x = [int&]/[long]導致右值不了的。

+4

'a'不是參考,它是一個簡單的'長'。 – LogicStuff

+3

^^^^^^ [是的,只是'長'](http://ideone.com/lGpcWt) – StoryTeller

+2

如果你不明白爲什麼它很長,原因是類型提升。你應該[閱讀這個答案](http://stackoverflow.com/questions/6770258/how-do-promotion-rules-work-when-the-signedness-on-either-side-of-a-binary -opera) – StoryTeller

回答

4

ir/L的結果是long。對於arithmetic operator,當二元運算符有不同的類型時,產生的結果將是通用類型;在intlong之間,它將是long

因此auto a = ir/L;a的類型是long。它不能傳遞給foo(int&),因爲你不能將左值引用綁定到不同類型的非const值。

。另一方面,鑑於L類型爲int,然後auto a = ir/L;a的類型將是int,那麼一切都很好。

關於「錯誤的右值部分」,當你通過一個longfoo(int&),首先編譯器會嘗試將其轉換爲int,這是一個臨時的(即右值),並不能必然左值引用非const。

long可以隱式轉換爲int,和臨時可以被綁定到左值參考常量,所以傳遞long變量既bar(int x)bar(const int&)是好的。

BTW:當您編寫int a = ir/L;時,類型long的結果隱式轉換爲int。所以你會得到一個int然後它可以通過foo(int&)

+0

我明白了。我從來沒有考慮過創建臨時值的類型轉換(錯誤消息中的右值)。這非常合理。謝謝。 –

1

您已使用auto的事實不相關。

along類型,由於參數提升規則。

foo因爲通過引用取參數,彙編自一個int&不能結合到long類型(即使它們具有相同的尺寸並且具有相同的補碼錶示)失敗。

+0

'int const&'會很好地綁定到臨時縮小的「int」。 – StoryTeller

+0

@StoryTeller:絕對! – Bathsheba