C++ 为什么数组会衰减为模板函数中的指针
我不明白为什么数组会衰减为模板函数中的指针 如果查看以下代码:当参数被强制为引用(函数f1)时,它不会衰减。在另一个函数f中,它衰减。为什么函数f中的T的类型不是const char(buff&)[3],而是const char*(如果我理解正确的话)C++ 为什么数组会衰减为模板函数中的指针,c++,arrays,templates,sizeof,C++,Arrays,Templates,Sizeof,我不明白为什么数组会衰减为模板函数中的指针 如果查看以下代码:当参数被强制为引用(函数f1)时,它不会衰减。在另一个函数f中,它衰减。为什么函数f中的T的类型不是const char(buff&)[3],而是const char*(如果我理解正确的话) #包括 模板 空f(T buff){ std::cout因为数组不能作为函数参数按值传递。 当您按值传递它们时,它们会衰减为指针 在该功能中: template <class T> void f(T buff) { 因为函数不能有数
#包括
模板
空f(T buff){
std::cout因为数组不能作为函数参数按值传递。
当您按值传递它们时,它们会衰减为指针
在该功能中:
template <class T>
void f(T buff) {
因为函数不能有数组作为参数。它们可以有数组引用。原因基本上归结为匹配不同重载时的类型推断。当调用f
时,编译器将类型推断为const char[3]
然后衰减为const char*
,因为数组就是这样做的。这与在f(1)
中编译器推断T为int
而不是int&
的方法完全相同
在f1
的情况下,因为参数是通过引用获取的,所以编译器再次推断T为const char[3]
,但它引用了它
没有什么真正令人惊讶的,但如果不是数组在用作函数参数时衰减为指针的话,它是一致的…引用规范,它说
(14.8.2.1/2)如果p不是参考类型:-如果a是阵列类型,
数组到指针标准转换生成的指针类型
(4.2)用于代替类型扣减;否则
所以,在你的情况下,很明显
template <class T>
void f1(T& buff) {
std::cout << "f:buff size:" << sizeof(buff) << std::endl; //prints 3
}
模板
无效f1(T和buff){
std::cout这是因为数组不能按值传递给函数。因此,为了使其工作,数组衰减为指针,然后按值传递给函数
换句话说,按值传递数组类似于用另一个数组初始化数组,但是在C++中,数组不能用另一个数组初始化:
char buff[3] = {0,0,0};
char x[3] = buff; //error
因此,如果数组出现在=
的右侧,则左侧必须是指针
或参考
类型:
char *y = buff; //ok - pointer
char (&z)[3] = buff; //ok - reference
演示:
这完全是出于同样的原因,auto
在以下每种情况下的推断都不同(请注意,auto
随C++11提供):
演示:我认为它们不能按值传递的原因与缺少副本/赋值有关。(尽管我无法理解为什么缺少这些内容)@ MooingDuck:在C++中,原因是,在C中,特定行为是从C.继承的,原因当然是不同的……@ MOOIGNEDIG:当然,这是使代码立即优于原始C语言的原因之一。因此,问题是,我们希望保持<代码> f(t填充)。
签名,但强制模板推断为引用类型。我们可以在客户端(调用站点)使用std::add_reference
或boost::ref
或其他方法,然后将pass by ref作为原始数组类型(未衰减)就像我们想要的一样?@v.oddou:实际上你可以试试这个,代码相对较短。而且这与当前的问题无关。但是std::add_reference
对你没有任何帮助(因为它只是tmp,只允许你定义一个类型(即char(&buff)[3]
)。这仍然不会绑定到第一个函数。但是boost::ref
将构建一个类型为boost::reference\u wrapper
的对象,该对象可以通过值进行传递。如果您只是将int
传递给f
,那么T
将是int
,而不是int&/code>。因此,您应该询问类似的问题e“为什么函数f中的T类型不是const char[3]
,而是const char*
?”(注意与您的答案相比缺少&
)(从我上一条评论中继续)。C/C++语言最愚蠢的一点是,如果您将const char[3]在代码中,编译器将默默地将它改写为<代码> const char */COD>。例如,这不会发生在本地变量上。我真的认为这应该导致当前的警告(至少从C++编译器)。
char buff[3] = {0,0,0};
char x[3] = buff; //error
char *y = buff; //ok - pointer
char (&z)[3] = buff; //ok - reference
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