why does the array decay to a pointer in a template function

百般思念 提交于 2019-11-29 15:09:38

问题


I don't understand why the array decays to a pointer in a template function.

If you look at the following code: When the parameter is forced to be a reference (function f1) it does not decay. In the other function f it decays. Why is the type of T in function f not const char (buff&)[3] but rather const char* (if I understand it correctly)?

#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;
}

回答1:


Because arrays can not be passed by value as a function parameter.
When you pass them by value they decay into a pointer.

In this function:

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

T can not be char (&buff)[3] as this is a reference. The compiler would have tried char (buff)[3] to pass by value but that is not allowed. So to make it work arrays decay to pointers.

Your second function works because here the array is passed by reference:

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

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



回答2:


It is because arrays cannot be passed by value to a function. So in order to make it work, the array decays into a pointer which then gets passed to the function by value.

In other words, passing an array by value is akin to initializing an array with another array, but in C++ an array cannot be initialized with another array:

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

So if an array appears on the right hand side of =, the left hand side has to be either pointer or reference type:

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

Demo : http://www.ideone.com/BlfSv

It is exactly for the same reason auto is inferred differently in each case below (note that auto comes with 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])

Output:

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

Demo : http://www.ideone.com/aXcF5




回答3:


To quote from spec, it says

(14.8.2.1/2) If P is not a reference type: — If A is an array type, the pointer type produced by the array-to-pointer standard conversion (4.2) is used in place of A for type deduction; otherwise

So, in your case, It is clear that,

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

doesn't decay into pointer.




回答4:


Because functions can't have arrays as arguments. They can have array references though.




回答5:


The reason basically boils down to type deduction when matching the different overloads. When you call f the compiler deduces the type to be const char[3] which then decays into const char* because that's what arrays do. This is done in the same exact way that in f(1) the compiler deduces T to be int and not int&.

In the case of f1 because the argument is taken by reference, then the compiler again deduces T to be const char[3], but it takes a reference to it.

Nothing really surprising, but rather consistent if it were not for the decay of arrays to pointers when used as function arguments...




回答6:


In f1(), Size 4 is size of pointer which is 4 bytes. because in this function you have a pointer to the array.

In f1(), you have that array by reference(or another name), and it is real array size.



来源:https://stackoverflow.com/questions/7797839/why-does-the-array-decay-to-a-pointer-in-a-template-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!