当auto用于数组时,为什么它被转换为指针而不是引用?

iam*_*ind 18 c++ arrays language-design c++11

见下面的例子:

int arr[10];
int *p = arr; // 1st valid choice
int (&r)[10] = arr; // 2nd valid choice
Run Code Online (Sandbox Code Playgroud)

现在,当我们用auto反对arr的话,它选择的第一选择.

auto x = arr; // x is equivalent to *p
Run Code Online (Sandbox Code Playgroud)

是否有理由选择指针而不是数组的引用

Naw*_*waz 24

是.在该表达式中,由于lvalue-to-rvalue转换,数组衰减为指针类型.

如果你想要数组类型,而不是指针类型,那么执行以下操作:

auto & x = arr; //now it doesn't decay into pointer type!
Run Code Online (Sandbox Code Playgroud)

& 在目标类型中防止数组衰减为指针类型!


x 是一个数组而不是指针,可以证明为:

void f(int (&a)[10]) 
{
    std::cout << "f() is called. that means, x is an array!" << std::endl;
}
int main() {
     int arr[10];
     auto & x = arr; 
     f(x); //okay iff x is an int array of size 10, else compilation error!
}
Run Code Online (Sandbox Code Playgroud)

输出:

f() is called. that means, x is an array!
Run Code Online (Sandbox Code Playgroud)

在ideone上演示:http://www.ideone.com/L2Ifp

请注意,f 无法使用指针类型调用.可以使用int大小数组调用它10.尝试使用任何其他类型调用它将导致编译错误.


Den*_*ose 5

为了提供行为的标准参考,7.1.6.4 [dcl.spec.auto]第6段内容如下:

一旦根据8.3确定了declarator-id的类型,使用declarator-id声明的变量的类型是使用模板参数推导的规则从其初始化程序的类型确定的.令T为已为变量标识符d确定的类型.通过用一个新发明的类型模板参数U替换auto的出现来从T获得P ...对于变量d推导出的类型然后是使用函数调用中的模板参数推导规则确定的推导A(14.8) .2.1),其中P是函数模板参数类型,d的初始值设定项是相应的参数.如果扣除失败,则声明格式不正确.

所以我们需要寻找其他地方,特别是14.8.2.1 [tmp.deduct.call]第2段:

如果P不是引用类型: - 如果A是数组类型,则使用数组到指针标准转换(4.2)生成的指针类型代替A来进行类型推导

为了完整起见,4.2 [conv.array]第1段:

可以将"数组的NT"或"未知的T的数组"类型的左值或右值转换为"指向T的指针"的prvalue.结果是指向数组的第一个元素的指针.

要逐步执行它,auto x = arr;创建一个虚构的函数template<typename P> f(P);并尝试P从调用中推导出来f(arr). A在这种情况下array of 10 int,并且P不是参考类型,因此A变为pointer to int.它将链条渗透回最终类型x.

所以基本上,它被视为指针,因为规则说它必须.这种行为更加有用,因为数组不可分配.否则,你auto x = arr;将无法编译而不是做一些有用的事情.