英文:
C++ idempotence of going through: pointer → reference → pointer
问题
我的理解
-
在C++中,可以使用
&value
将普通值转换为指向自身的指针,或者通过隐式转换将其转换为对自身的引用。 -
与Rust不同,引用不是实际的一等类型,而只是某些类型声明位置接受的二进制限定符。可以透明地将引用用作其被引用的对象,隐藏了内部指针1。因此,我们可以使用
&refToValue
立即获取对被引用对象的指针。
问题
如果我将指针转换为引用,然后再转换回指针,我是否保证会得到原始指针? 这在Rust中是这样的,但再次提醒,Rust将第一类引用定义为抽象化的“正常”类型,用来封装指针。
// 由 @chi 提供的示例代码
T x;
T* ptr1 = &x;
T& ref = *ptr1;
T* ptr2 = &ref;
assert(ptr1 == ptr2); // 根据规范,这是否总是成立?
1:我知道C++标准不要求将引用实现为指针,但我看不出它们可以以其他方式实现(不考虑特定上下文的优化),尤其是如果对我的最后一个问题的答案是“是”的话。
英文:
My understanding
-
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 pointer<sup>1</sup>. As such, we can use
&refToValue
to obtain a pointer to the referee immediately.
Question
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?
<sub>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".</sub>
答案1
得分: 7
Oh, you're diving into some pointer and reference fun, huh? 🤪
So, you have this little adventure with T
, ptr1
, ref
, and ptr2
, right? 🚀
Here's the magical answer: Yes! 🌟
You see, when you do all those pointer and reference dances, you end up with ptr2
pointing right back to where ptr1
started. It's like a treasure map that leads you back to the same spot! 🗺️💎
So, don't worry, you're guaranteed to get the original pointer back on this whimsical journey! 🎩🐇
英文:
>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.
Full explanation on the initialisations
-
Per
[expr.unary.op]/3.2
,T* ptr1 = &x
initializesptr1
as a pointer toT
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. -
Per
[expr.unary.op]/1
and[dcl.ref]/5
,T& ref = *ptr1
initializesref
to refer to a valid object, namelyx
as*ptr1
performs indirection onptr1
and yields an lvalue denoting the object to whichptr1
points, namelyx
.
>[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. -
Finally, per
[expr.unary.op]/3.2
again,T* ptr2 = &ref
initializesptr2
as a pointer toT
pointing to the designated object (x
).
What about the pointer comparison?
- As per the equality of the two pointers, I raise
[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
.
答案2
得分: 3
> If I convert a pointer, to a reference, back to a pointer, am I guaranteed to get the original pointer back?
是的。
> references aren't actual first-class types ... binary qualifier that some type declaration sites accept
的确,虽然引用是类型,但它们不能作为表达式类型。
所以例如,当您执行&*foo
时,*foo
不是一个引用。
英文:
> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论