When auto is used against array, why it's converted to pointer and not reference?
See the below example:
int arr[10];
int *p = arr; // 1st valid choice
int (&r)[10] = arr; // 2nd valid choice
Now when we use auto
against arr
then, it chooses the 1st choice.
auto x = arr; // x is equivalent to *p
Is there a reason for choosing a pointer and not 开发者_C百科reference for array ?
Yes. In that expression, the array decays into pointer type, due to lvalue-to-rvalue
conversion.
If you want array type , not pointer type, then do this:
auto & x = arr; //now it doesn't decay into pointer type!
&
in the target type prevents the array from decaying into pointer type!
x
is an array and not a pointer, can be proved as:
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!
}
Output:
f() is called. that means, x is an array!
Demo at ideone : http://www.ideone.com/L2Ifp
Note that f
cannot be called with pointer type. It can be called with an int
array of size 10
. Attempting to call it with any other type, will result in compilation error.
auto
produces values. It will not produce references. With this in mind, then the pointer is the trivial conversion to a value that the array offers.
To provide a standard reference for the behavior, 7.1.6.4 [dcl.spec.auto] paragraph 6 reads:
Once the type of a declarator-id has been determined according to 8.3, the type of the declared variable using the declarator-id is determined from the type of its initializer using the rules for template argument deduction. Let T be the type that has been determined for a variable identifier d. Obtain P from T by replacing the occurrences of auto with ... a new invented type template parameter U ... The type deduced for the variable d is then the deduced A determined using the rules of template argument deduction from a function call (14.8.2.1), where P is a function template parameter type and the initializer for d is the corresponding argument. If the deduction fails, the declaration is ill-formed.
So we need to look elsewhere, specifically 14.8.2.1 [tmp.deduct.call] paragraph 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
For completeness sake, 4.2 [conv.array] paragraph 1:
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.
To step through it, auto x = arr;
creates an imaginary function template<typename P> f(P);
and attempts to deduce P
from the call f(arr)
. A
in this case is array of 10 int
, and P
is not a reference type, so A
becomes pointer to int
instead. Which percolates up the chain back into the final type of x
.
So basically, it is treated as a pointer because the rules say it must. The behavior is simply more useful this way, since arrays are not assignable. Otherwise, your auto x = arr;
would fail to compile rather than do something useful.
For an array arr
, the expression arr
itself means &arr[0]
. This rule comes from C. Therefore, IMO, auto chooses pointer.
精彩评论