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

时间:2011-10-17 18:20:19

标签: c++ arrays templates sizeof

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

如果查看以下代码:当参数被强制为参考(函数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;
}

6 个答案:

答案 0 :(得分:10)

这是因为 arrays 不能通过值传递给函数。因此,为了使其工作,数组衰减成一个指针,然后通过值传递给函数

换句话说,按值传递数组类似于使用另一个数组初始化数组,但在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

答案 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()中,您通过引用(或其他名称)获得该数组,并且它是实际数组大小。