推迟返回的参考
Deferencing a returned reference
给定:
int& foo(); // don't care what the reference is to
int intVal;
在以下两种情况下,右侧是相同的函数调用
int& intRef = foo();
intVal = foo(); // a reference is returned... a value is assigned.
在第二种情况下,返回的引用如何"转换"到值?
是由分配运营商完成的INT?
在语言层面上,没有诸如"退出参考"之类的概念。引用实现了 lvalue 的概念。变量和参考基本上是同一件事。变量和参考之间的唯一区别是,该变量是由编译器自动绑定到存储中的位置,而通常在运行时通过用户操作绑定了参考。
在您的示例中,intRef
和intVal
之间没有概念上的差异。两者都是int
型的lvalues。在概念层面上,两者都是通过相同的机制访问的。您甚至可以将程序中的所有变量视为参考文献,这些变量是由编译器隐含的。这基本上是Bjarne Stroustrup在TC PL中的含义(而不是逐字化),人们可以将参考视为现有变量的替代名称。
唯一可感知两者之间的差异的时刻是创建这些实体并初始化它们。参考的初始化是将其绑定到存储中某些位置的行为。变量的初始化是将初始值复制到现有存储中的行为。
但是,一旦初始化了参考,它就可以作为普通变量:读取/写作的行为是读取/编写其绑定的存储位置的行为。将参考评估的地址评估到其绑定的存储位置的地址。等等。
在许多情况下,在内部将参考作为伪装的指针实现,即作为无形指针,每次访问它时都会为您隐含地使用它。在这种情况下(当它通过指针真正实现时),每次您访问它时,都会再次进行解释。因此,正如您在问题中提出的那样,不是任务操作员。您在代码中提到该参考的名称的事实是,导致无形指针被删除。
但是,实现"现有变量的替代名称"的实体并不一定需要存储自身,即用汇编的语言,不需要任何材料代表的东西,例如隐藏的指针。这就是为什么8.3.2中语言标准指出"未指定是否需要存储的情况"。
foo
正在返回一些引用类型" int"的对象。我们不在乎" int"的来源,我们只是假设它存在。
第一行int& intRef = foo()
创建intRef
,它也指类型" int"的对象与foo
的返回值。
第二行,intVal
的值被返回的参考所指的对象的值代替。
回应您的评论:
您似乎对指针和参考文献感到非常困惑。引用就像一个对象的别名。对参考进行任何操作实际上会影响其指的对象。
没有提起参考的东西。您只能取消指针。提出的行为是使用Unary *
操作员将对象指向一个点。例如,如果您有int* p
,则可以执行*p
以获取指向的对象。这是 dereferencing p
。
您唯一可以在引用上执行*
的时间是它指的是指针(或者它过载operator*
)。在您的情况下,由于foo
返回int&
,因此我们无法将其解释。表达式*foo()
只是不会编译。这是因为foo
的返回值具有" INT"类型,这不是指针,也不超载operator*
。
出于所有意图和目的,您可以将从foo
返回的参考视为它所指的对象。将此值分配给intVal
确实与在以下代码中为intVal
分配x
并没有什么不同:
int intVal;
int x = 5;
intVal = x;
我确定您了解,intVal
被赋予x
的值。这仅由标准来定义:
在简单分配(
=
)中,表达式的值替换了左操作数所指对象的值。
根本不需要转换,因为操作员的两侧都是相同的类型。
这与您的情况确实没有什么不同。您只有:
intVal = some_ref_to_int;
其中some_ref_to_int
是表达式foo()
。这是参考的事实并不重要。intVal
接收参考表示的对象的值。
分配给 intVal
是标准中5.17 [exp.ass]中定义的 sigsment-expression 。根据其他几个语法规则,分配表达的语法规则非常复杂,但基本上您需要在=
操作员的左侧进行修改的LVALUE,右边的Prvalue表达式手部。
在
的情况下intVal = foo();
RHS上的表达式是类型int
的lvalue,因此内置的lvalue-to-rvalue转换发生了...这几乎不是转换,因为该值不会改变,并且类型也不会改变(除了删除基本类型的基本类型,因此,如果LVALUE是型号const int
,则Prvalue将为int
类型)。[cons.lval]说
非功能,非阵列类型
T
的glvalue(3.10)可以转换为prvalue。[...]如果T
是一种非类型类型,则PRVALUE的类型是T
的CV UNQUALIFIED版本。否则,Prvalue的类型为T
。[...] glvalue指示的对象中包含的值是prvalue结果。
因此,prvalue具有类型的int
,并且与foo()
相同的值,即与返回的引用绑定到的变量相同的值。
分配表达式的规则说:
在简单分配(
=
)中,表达式的值替换了左操作数所指的对象的值。
因此,intVal
的值将被Prvalue的值所取代。规则继续:
如果左操作数不是类型,则该表达式被隐式转换为左操作数的CV UNQUALIFIED类型。
因此,由于int
不是类类型(因此没有过载的operator=
,因此仅使用内置分配运算符),分配将将RHS转换为int
,这是您的情况下已经具有的类型。p>因此, intVal
的值设置为prvalue的值,我们说这是glvalue表达式 foo()
的值,即变量的值,引用绑定到。
请注意,LVALUE-RED-REGRAUE转换与RHS是参考无关。同样的事情在这里发生:
int val = 0;
intVal = val;
val
是类型int
的LVALUE,因此将其转换为int
类型的Prvalue,intVal
的值设置为该prvalue的值。
规则是用表达式的"值类别"(即lvalue或rvalue)表示的,而不是是否是参考。所需的参考文献的任何"删除"都是由编译器隐式和不可见的,以实施所需的行为。
- 赋值运算符的返回值可以作为参考吗?
- C 标准:通过复制返回以初始化无RVO的参考:是否有任何副本
- JNI返回Java对象,可以返回本地参考,还是必须是全局
- 是否可以通过引用通过参数返回参考
- 返回int数据类型v/s传递参考
- 通过C 中的参考返回结果
- 在C 中返回参考有效期参考是否有效
- 通过参考返回C 中的对象
- 为什么const rvalue合格的std ::可选:: value()返回const rvalue参考
- C 通过参考返回本地对象
- C 按值返回与参考返回
- 为什么未调用具有常量参考返回值的超载方法
- 如何检查正确操作数以通过参考返回功能
- 移动后通过rvalue参考返回
- 在C 中参考返回的参数中积累事物是一种气味吗?
- 我应该始终处理参考返回矢量吗?
- 通过参考返回和const函数返回const值的函数之间的差异
- C 常数参考返回算法=作为非函数的声明
- 为什么我们在分配运算符过载中使用参考返回,而不是在加上Minus OPS中使用
- C 参考和类对象的非参考返回 - 为什么输出相同