I think the place you are stumbling is actually with the expression c.getObj()
in the line return c.getObj();
.
You think the expression c.getObj()
has type const Int&
. However that is not true; expressions never have reference type. As noted by Kerrek SB in comments, we sometimes talk about expressions as if they had reference type, as a shortcut to save on verbosity, but that leads to misconceptions so I think it is important to understand what is really going on.
The use of a reference type in a declaration (including as a return type as in getObj
's declaration) affects how the thing being declared is initialized, but once it is initialized, there is no longer any evidence that it was originally a reference.
Here is a simpler example:
int a; int &b = a; // 1
versus
int b; int &a = b; // 2
These two codes are exactly identical (except for the result of decltype(a)
or decltype(b)
which is a bit of a hack to the system). In both cases the expressions a
and b
both have type int
and value category "lvalue" and denote the same object. It's not the case that a
is the "real object" and b
is some sort of disguised pointer to a
. They are both on equal footing. It's one object with two names.
Going back to your code now: the expression c.getObj()
has exactly the same behaviour as c.m_obj
, apart from access rights. The type is Int
and the value category is "lvalue". The &
in the return type of getObj()
only dictates that this is an lvalue and it will also designate an object that already existed (approximately speaking).
So the deduced return type from return c.getObj();
is the same as it would be for return c.m_obj;
, which -- to be compatible with template type deduction, as mentioned elsewhere -- is not a reference type.
NB. If you understood this post you will also understand why I don't like the pedagogy of "references" being taught as "disguised pointers that auto dereference", which is somewhere between wrong and dangerous.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…