Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么数组会衰减为模板函数中的指针_C++_Arrays_Templates_Sizeof - Fatal编程技术网

C++ 为什么数组会衰减为模板函数中的指针

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) { 因为函数不能有数

我不明白为什么数组会衰减为模板函数中的指针

如果查看以下代码:当参数被强制为引用(函数f1)时,它不会衰减。在另一个函数f中,它衰减。为什么函数f中的T的类型不是const char(buff&)[3],而是const char*(如果我理解正确的话)

#包括
模板
空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