`auto` specifier type deduction for references
Let's consider the following code snippet
void Test()
{
int x = 0;
int& rx = x;
int* px = &x;
auto apx = px; // deduced type is int*
auto arx = rx; // deduced type is int
}
One could draw an analogy from pointer types expecting that the deduced type of arx
is int&
, but it is int
in fact.
What is the rule in Standard which governs that? What is the reason behind it? Sometimes I get caught by it in a case like this:
const BigClass& GetBigClass();
...
auto ref_bigclass = GetBigClass(); // unexpected copy is performed
Use auto&
:
auto& ref_bigclass = GetBigClass();
References are supposed to be transparent: any operation on them happens on the object they refer to, there is no way to 'get' reference itself.
UPD: This is covered in 7.1.6.4/6:
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.
And template argument deduction is defined in 14.8.2.1/3:
If template parameter type P is a reference type, the type referred to by P is used for type deduction.
P.S. Note that this is different for decltype
: decltype(rx)
will yield int&
type (7.1.6.2/4).
The simplest way to think about it is comparing it to template argument deduction.
Given:
template<typename T>
void deduce(T) { }
If you call:
deduce(px);
then the template argument T
will be deduced as int*
and if you call
deduce(rx);
then T
will be deduced as int
, not int&
You get the same types deduced when using auto
.
One could draw an analogy from pointer types expecting that the deduced type of
arx
isint&
You'd have to have a fairly confused model of the C++ language to make that analogy. Just because they are declared in syntactically similar ways, as Type@
with a type and a modifier doesn't make them work the same way. A pointer is a value, an object, and it can be copied and have its value altered by assignment. A reference is not an object, it's a reference to some object. A reference can't be copied (copying it copies the referent) or altered (assigning to it alters the referent). A function that returns a pointer returns an object by value (the object in question being a pointer object), but a function that returns a reference (like your GetBigClass()
) returns an object by reference. They're completely different semantics, trying to draw analogies between pointers and references is doomed to failure.