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

发布于 2024-12-10 06:41:34 字数 710 浏览 0 评论 0原文

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

如果您查看以下代码:当参数被强制为引用(函数 f1)时,它不会衰减。在另一个函数 f 中它会衰减。为什么函数 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;
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

太阳哥哥 2024-12-17 06:41:34

这是因为数组无法按值传递给函数。因此,为了使其正常工作,数组会衰减为一个指针,然后按值传递给函数。

换句话说,按值传递数组类似于用另一个数组初始化一个数组,但在 C++ 中一个数组不能用另一个数组初始化数组:

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

因此,如果数组出现在 = 的右侧,则左侧必须是 pointerreference 类型:

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

演示:<一href="http://www.ideone.com/BlfSv" rel="noreferrer">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

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

鲜肉鲜肉永远不皱 2024-12-17 06:41:34

因为数组不能作为函数参数按值传递。
当您按值传递它们时,它们会退化为指针。

在此函数中:

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]

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]
感情旳空白 2024-12-17 06:41:34

引用规范,它说

(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
}

不会衰减为指针。

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.

你是年少的欢喜 2024-12-17 06:41:34

因为函数不能将数组作为参数。但它们可以有数组引用。

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

就是爱搞怪 2024-12-17 06:41:34

原因基本上可以归结为匹配不同重载时的类型推导。当您调用 f 时,编译器会将类型推导为 const char[3],然后衰减为 const char* 因为这就是数组可以。。其完成方式与在 f(1) 中编译器将 T 推导为 int 而不是 int& 的方式完全相同。

f1 的情况下,因为参数是通过引用获取的,所以编译器再次将 T 推导为 const char[3],但它需要对其的引用。

没有什么真正令人惊讶的,但如果不是数组用作函数参数时衰减,那么就会保持一致......

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文