In C++, an normal value can be converted to a pointer to itself using &value
, or to a reference to itself through implicit cast.
As opposed to Rust, references aren't actual first-class types but merely a binary qualifier that some type declaration sites accept. References can be used transparently as if they were their referee, hiding away the internal pointer1. As such, we can use &refToValue
to obtain a pointer to the referee immediately.
If I convert a pointer, to a reference, back to a pointer, am I guaranteed to get the original pointer back? This would be the case in Rust, but again, Rust has first-class references defined as "normal" types abstracting over a pointer.
// Sample code by @chi
T x;
T* ptr1 = &x;
T& ref = *ptr1;
T* ptr2 = &ref;
assert(ptr1 == ptr2); // Is that always true according to the spec?
1: I know that the C++ standard doesn't require references to be implemented as pointers, but I cannot see how they could be implemented in any other way (not considering context-specific optimizations), especially if the answer to my final question is "yes".
If I convert a pointer, to a reference, back to a pointer, am I guaranteed to get the original pointer back?
T x; T* ptr1 = &x; T& ref = *ptr1; T* ptr2 = &ref;
Yes.
[expr.unary.op]/3.2
, T* ptr1 = &x
initializes ptr1
as a pointer to T
pointing to the designated object (x
).The operand of the unary & operator shall be an lvalue of some type T. The result is a prvalue.
...
(3.2) Otherwise, the result has type “pointer to T” and points to the designated object ([intro.memory]) or function ([basic.compound]). If the operand names an explicit object member function ([dcl.fct]), the operand shall be a qualified-id.
[expr.unary.op]/1
and [dcl.ref]/5
, T& ref = *ptr1
initializes ref
to refer to a valid object, namely x
as *ptr1
performs indirection on ptr1
and yields an lvalue denoting the object to which ptr1
points, namely x
.
[expr.unary.op]/1
The unary * operator performs indirection. Its operand shall be a prvalue of type “pointer to T”, where T is an object or function type. The operator yields an lvalue of type T denoting the object or function to which the operand points.
[dcl.ref]/5
A reference shall be initialized to refer to a valid object or function.
[expr.unary.op]/3.2
again, T* ptr2 = &ref
initializes ptr2
as a pointer to T
pointing to the designated object (x
).[basic.compound]/3.4
:A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object35 or the first byte in memory after the end of the storage occupied by the object, respectively.
and [expr.eq]/3.2
:
[refering to the result of ==, as per defined in /1]
if the pointers are both null, both point to the same function, or both represent the same address, they compare equal.
Meaning, regardless of the actual value of ptr1
and ptr2
:
ptr1 == ptr2
yields true
.
If I convert a pointer, to a reference, back to a pointer, am I guaranteed to get the original pointer back?
Yes.
references aren't actual first-class types ... binary qualifier that some type declaration sites accept
Indeed, while references are types, they can't serve as expression types.
So e.g. when you do &*foo
, *foo
isn't a reference.
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