我不明白为什么数组会衰减到模板函数中的指针。
如果查看以下代码:当参数被强制为参考(函数f1)时,它不会衰减。在另一个函数中,它衰减了。为什么函数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 :(得分:10)
这是因为 arrays 不能通过值传递给函数。因此,为了使其工作,数组衰减成一个指针,然后通过值传递给函数。
换句话说,按值传递数组类似于使用另一个数组初始化数组,但在C ++中数组不能初始化使用另一个数组:
char buff[3] = {0,0,0};
char x[3] = buff; //error
因此,如果数组显示在=
的右侧,则左侧必须是pointer
或reference
类型:
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
答案 1 :(得分:9)
因为数组不能通过值作为函数参数传递 当你按值传递它们时,它们会衰减成指针。
在此功能中:
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]
答案 2 :(得分: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
}
不会衰减成指针。
答案 3 :(得分:1)
因为函数不能将数组作为参数。他们可以有数组引用。
答案 4 :(得分:1)
当匹配不同的重载时,原因基本上归结为类型推导。当您调用f
时,编译器会将类型推断为const char[3]
,然后衰减到const char*
,因为这就是数组所做的。这与在f(1)
中编译器将T推导为int
而非int&
的方式完全相同。
在f1
的情况下,因为参数是通过引用获得的,然后编译器再次将T推导为const char[3]
,但它会引用它。
当用作函数参数时,如果不是指针的衰减,那么没有什么可以令人惊讶的,但是相当一致......
答案 5 :(得分:0)
在f1()
中,大小4
是指针的大小,为4个字节。因为在这个函数中你有一个指向数组的指针。
在f1()
中,您通过引用(或其他名称)获得该数组,并且它是实际数组大小。