![](/img/trans.png)
[英]General rules of passing/returning reference of array (not pointer) to/from a function?
[英]Function argument binding rules for passing an array by reference vs passing pointer
為了防止任何混淆,我非常理解數組和指針之間的區別,衰減到指針的概念,以及在C ++中通過引用傳遞數組的概念等。
這里我的問題具體是關於編譯器從一組函數重載候選中選擇函數的規則,當一個重載采用數組引用時,另一個重載采用指針。
例如,假設我們有:
template <class T, std::size_t N>
void foo(const T (&arr)[N])
{
std::cout << "Array-reference overload!" << std::endl;
}
template <class T>
void foo(const T* ptr)
{
std::cout << "Pointer overload!" << std::endl;
}
如果我們嘗試按如下方式調用函數模板foo()
:
const char arr[2] = "A";
foo(arr);
...然后我的期望是編譯器將選擇第一個重載,即采用數組引用的重載。
但是,使用GCC 4.9.2,如果我編譯上面的代碼,我會收到一個錯誤:
test.cpp:28:9: error: call of overloaded ‘foo(const char [2])’ is ambiguous
我不清楚為什么這兩個重載被編譯器認為是同樣好的候選者,因為第一個重載完全匹配類型,而第二個重載需要額外的衰減到指針步驟。
現在,我可以通過顯式使用type_traits
來實現上述重載,如下所示:
template <class T, std::size_t N>
void foo(const T (&arr)[N])
{
std::cout << "Array-reference overload!" << std::endl;
}
template <class T>
void foo(T ptr, typename std::enable_if<std::is_pointer<T>::value>::type* = 0)
{
std::cout << "Pointer overload!" << std::endl;
}
在這種情況下,程序編譯並選擇采用數組引用的重載。 但是,我不明白為什么這個解決方案應該是必要的。 我想理解為什么編譯器認為一個函數需要衰減指針作為數組引用同樣可能的重載候選,當傳遞的參數非常多的是數組時。
第一個重載完全匹配類型,而第二個重載需要額外的衰減到指針步驟。
因為在重載分辨率中檢查隱式轉換序列的排名時, 數組到指針的轉換被認為是完全匹配,因此第二個重載與第一個重載具有相同的等級。
從標准, $ 16.3.3.1.1標准轉換序列[over.ics.scs]表13 - 轉換
Conversion Category Rank Subclause No conversions required Identity Exact Match ... ... Array-to-pointer conversion Lvalue Transformation Exact Match [conv.array] ... ...
值得注意的是,“無需轉換”(即第一次超載的情況)的等級也是“完全匹配”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.