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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With