2017-08-25 95 views
6

我有一個關於C++模板的問題。以下代碼段錯誤。在C++模板中的段錯誤

template <typename T1, typename T2> 
inline T1 const& max(T1 const &a, T2 const &b) { 
    return a < b ? b : a; 
} 
int main() { 
    std::cout << max(4.9, 4) << std::endl; 
} 

但是,刪除&,它做對了。

template<typename T1, typename T2> 
inline T1 const max(T1 const &a, T2 const &b) { 
    return a < b ? b : a; 
} 
int main() { 
    std::cout << max(4.9, 4) << std::endl; 
} 

此外,只是使用T代替T1和T2,它工作得很好。

template<typename T> 
inline T const& max(T const &a, T const &b) { 
    return a < b ? b : a; 
} 

int main() { 
    std::cout << max(4, 5) << std::endl; 
} 

我在做什麼錯在這裏?

+0

請提及您正在使用的編譯器,包括版本號。如果它是GCC,你用'-Wall'編譯了嗎?您可能會忽略一個警告,導致未定義的行爲。 –

+0

編譯器應該告訴你max()調用返回對臨時的引用。 – tristan

+1

前兩個代碼片段是相同的? – asimes

回答

10

您應該始終編譯並打開警告,請參閱https://wandbox.org/permlink/KkhFOJw6QNJ7rv7J。如果你有警告標誌,編譯器會幫助你,並告訴你你做錯了什麼。

這裏發生了什麼是促銷活動(請參閱Return type of '?:' (ternary conditional operator)),您在intdouble上執行三元表達式。這樣做會導致臨時升級double。並返回一個臨時引用的引用,並在其生命週期綁定的函數返回後返回未定義的行爲。

1

在兩個第一,你正在返回一個臨時引用。

爲什麼?那麼,你的函數返回類型T1,但你將不得不轉換你發送的類型之一。轉換會創建正確類型的臨時文件。然後你回來了。

由於臨時死亡,返回的引用被綁定到一個死對象。

您已經找到修復程序。你要麼沒有返回一個引用,要麼你要麼採用相同類型的參數。

如果你看看標準的實現,它選擇了第二種解決方案:採用相同類型的參數。