2011-10-17 59 views
6

我不明白爲什麼數組衰減到模板函數中的指針。爲什麼數組衰減到模板函數中的指針

如果你看看下面的代碼:當參數被強制爲引用(函數f1)時,它不會衰減。在另一個函數f衰變。爲什麼函數f中的T類型不是const char(buff &)[3],而是const char *(如果我理解正確)?

#include <iostream> 

template <class T> 
void f(T buff) { 
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;  //prints 4 
} 

template <class T> 
void f1(T& buff) { 
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;  //prints 3 
} 

int main(int argc, char *argv[]) { 
    const char buff[3] = {0,0,0}; 
    std::cout << "buff size:" << sizeof(buff) << std::endl;   //prints 3 
    f(buff); 
    f1(buff); 
    return 0; 
} 
+0

如果你只是通過一個'in t'到'f',那麼'T'將是'int',而不是'int&'。因此,你應該問一些類似「爲什麼函數f中的T類型不是const char [3]'而是const char *'?」 (注意與你的答案相比缺少的'&') –

+0

...(繼續我最後的評論)。關於C/C++語言的最愚蠢的事情是,如果你把'const char [3]'放在你的參數中,編譯器會默默地將它重寫爲'const char *'。例如,這對局部變量不會發生。我真的認爲這應該導致現在的警告(至少從C++編譯器) –

回答

7

因爲數組不能作爲函數參數傳遞。
當你通過它們傳遞它們時,它們衰變成一個指針。

在這個函數中:

template <class T> 
void f(T buff) { 

T不能是char (&buff)[3]因爲這是一個參考。編譯器會嘗試使用char (buff)[3]來傳遞值,但這是不允許的。所以要讓它工作的陣列衰減指針。

你的第二個功能的作品,因爲這裏的數組是通過引用傳遞:

template <class T> 
void f1(T& buff) { 

// Here T& => char (&buff)[3] 
+0

我相信他們不能通過值傳遞的原因是缺乏複製/分配。 (雖然爲什麼這些都是我想念的) –

+0

@MooingDuck:在C++中,原因是特定的行爲是從C繼承的。在C中,原因會不同,當然... –

+1

@MooingDuck:當然這是一個使'std :: array <>'立即優於原始C數組。 – ildjarn

1

因爲函數不能有數組作爲參數。儘管它們可以有數組引用。

1

當匹配不同的過載時,原因基本歸結爲類型扣除。當您撥打f時,編譯器會將類型推斷爲const char[3],然後再衰減到const char*,因爲這就是陣列執行的操作。這與f(1)中編譯器將T推導爲int而不是int&的方式完全相同。

f1的情況下,因爲參數是通過引用獲取的,那麼編譯器會再次推斷T爲const char[3],但它需要引用它。

真的沒什麼奇怪的,而是一致的,如果作爲函數參數使用時沒有對數組的衰減的指針...

0

f1(),大小4是指針也就是4個字節的大小。因爲在這個函數中你有一個指向數組的指針。

f1()中,您通過引用(或其他名稱)具有該數組,並且它是實數組大小。

4

要從規範引用,它說

(14.8.2.1/2)如果P不是引用類型: - 如果A是一個數組類型, 由陣列到所產生的指針類型 - 使用指針標準轉換 (4.2)代替A進行類型扣除;否則

所以,你的情況,很顯然,

template <class T> 
void f1(T& buff) { 
    std::cout << "f:buff size:" << sizeof(buff) << std::endl;  //prints 3 
} 

不衰變成指針。

5

這是因爲數組不能通過函數。因此,爲了使其工作,數組衰減爲一個指針,然後通過值傳遞給函數

換句話說,由值傳遞數組是類似於初始化與另一陣列的陣列,但在C++ 陣列不能與另一個數組初始化

char buff[3] = {0,0,0}; 
char x[3] = buff; //error 

所以,如果數組出現在=的右側,左側必須爲pointerreference類型:

char *y = buff; //ok - pointer 
char (&z)[3] = buff; //ok - reference 

演示:http://www.ideone.com/BlfSv

正是出於同樣的原因是auto在下面每一種情況下推斷不同(請注意,auto帶有C++ 11):

auto a = buff; //a is a pointer - a is same as y (above) 
std::cout << sizeof(a) << std::endl; //sizeof(a) == sizeof(char*) 

auto & b = buff; //b is a reference to the array - b is same as z (above) 
std::cout << sizeof(b) << std::endl; //sizeof(b) == sizeof(char[3]) 

輸出:

4 //size of the pointer 
3 //size of the array of 3 chars 

演示:http://www.ideone.com/aXcF5