为什么右值没有地址?

Why don't rvalues have an address?

本文关键字:地址 为什么      更新时间:2023-10-16

为什么右值没有内存地址?当程序执行时,它们是否没有加载到RAM中,或者它是否引用存储在处理器寄存器中的值?

你的问题("为什么右值没有内存地址?")有点困惑。右值是一种表达式。表达式没有地址:对象有地址。更正确的问题是"为什么不能将地址操作符应用于右值表达式?"

这个问题的答案很简单:你只能取一个对象的地址,并不是所有的右值表达式都指向对象(例如,表达式42有一个值,但不指向对象)。

一些右值表达式确实引用对象,但这些对象缺乏持久性。右值表达式引用的对象是一个临时对象,在创建该对象的表达式结束时销毁。这样的对象确实有地址(你可以很容易地通过调用临时对象的成员函数发现这一点;this指针必须指向临时对象,因此临时对象必须有地址)。

这是左值表达式和右值表达式的根本区别。

左值表达式引用具有持久性的对象:左值表达式引用的对象在单个表达式之外持续存在。

rvalue视为表达式本身没有地址。但是表达式中涉及的对象确实有地址。可以取对象的地址,即使它是临时对象。

考虑这个,

const int & i = 10; //ok

这里,10是一个右值,因此显示 &i10的地址。不,这是错误的。&iint类型的临时对象的地址,该对象是由表达式10创建的。由于临时对象不能绑定到非const引用,所以我使用const。这意味着,下面是一个错误:

int & i = 10; //error

这个问题混合了与"规范"answers"实现"相关的两个不同方面。

"规范"定义了一些抽象规则,这些规则定义了语言相对于它所使用的抽象机器的行为方式。使"抽象机器"适应于其下的"真实机器"是编译器(而不是语言)的目的。

规范强制执行的是-从语言的角度来看-"存储"(具有适当地址的内存块)仅给予具有名称的对象(对于名称存在的作用域)或通过显式请求(new)动态分配的对象。其他一切都是"临时的":像对象一样赋值、复制和移动,但不需要存在在定义良好且稳定的位置。至少,不是为了语言的目的。

当然,它必须(物理地)留在某个地方,因此您可以-通过适当的强制转换或转换-尝试猜测内存地址。但是,如果您尝试积极使用它,语言规范不会授予任何一致的行为。这意味着不同的编译器可以表现出不同的行为,并根据它们所针对的实际机器进行更好的优化。

什么意思,右值确实有地址。试过

Type const value& = rvalue;
Type const* address = &value;

就拿这个例子来说

int a = 1 + 2;

1+2被解析为3。

问问自己:

  • 3是对象吗?
  • 3在内存中的位置?

当你需要一个对象的地址时,使用&

如果右值是可寻址的,这意味着你可以声明一个指针,指向你的计算机决定存储3

int* a = &3;

看起来对吗?:)