C++指针 → 引用 → 指针的幂等性

huangapple go评论86阅读模式
英文:

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 &amp;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 = &amp;x;
T&amp; ref = *ptr1;
T* ptr2 = &amp;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?
>
>
&gt;T x;
&gt;T* ptr1 = &amp;x;
&gt;T&amp; ref = *ptr1;
&gt;T* ptr2 = &amp;ref;
&gt;

Yes.


Full explanation on the initialisations

  • Per [expr.unary.op]/3.2, T* ptr1 = &amp;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.

  • Per [expr.unary.op]/1 and [dcl.ref]/5, T&amp; 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.

  • Finally, per [expr.unary.op]/3.2 again, T* ptr2 = &amp;ref initializes ptr2 as a pointer to T 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 &amp;*foo, *foo isn't a reference.

huangapple
  • 本文由 发表于 2023年7月17日 17:07:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76702953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定