为什么右值没有内存地址?它们是在程序执行时没有加载到 RAM 中还是引用存储在处理器寄存器中的值?
5 回答
您的问题(“为什么右值没有内存地址?”)有点困惑。右值是一种表达式。 表达式没有地址: 对象有地址。问“为什么不能将地址运算符应用于右值表达式?”会更正确。
答案相当简单:您只能获取对象的地址,并非所有右值表达式都引用对象(例如,表达式42
有值但不引用对象)。
一些右值表达式确实引用了对象,但这些对象缺乏持久性。右值表达式引用的对象是一个临时对象,并在创建它的表达式的末尾被销毁。这样的对象确实有地址(您可以通过在临时对象上调用成员函数很容易地发现这一点;this
指针必须指向临时对象,因此临时对象必须有地址)。
这是左值表达式和右值表达式之间的根本区别。左值表达式指的是具有持久性的对象:左值表达式所指的对象在单个表达式之外仍然存在。
将rvalue
其视为表达式的值。该值本身没有地址。但是表达式中涉及的对象确实有地址。您可以获取对象的地址,甚至可以是临时对象。
考虑到这一点,
const int & i = 10; //ok
这里,是一个10
右值,所以它看起来是. 不,那是错误的。是类型的临时对象的地址,它是根据表达式创建的。而且由于临时对象不能绑定到非常量引用,所以我使用. 这意味着,以下是一个错误:&i
10
&i
int
10
const
int & i = 10; //error
这个问题混合了与“规范”和“实施”相关的两个不同方面。
“规范”定义了一些抽象规则,这些规则定义了语言相对于它所使用的抽象机器的行为方式。使“抽象机器”适应其下的“真实机器”,这是编译器(而不是语言)的目的。
规范强制执行的是-从语言的角度来看-“存储”(具有正确地址的一块内存)仅提供给具有名称的对象(用于名称存在的范围的存在)或通过显式请求 ( new
) 动态分配。其他一切都是“临时的”:像对象一样分配、复制和移动,但不需要存在于定义明确且稳定的位置。至少,不是为了语言的目的。
当然,它必须(物理上)保留在某个地方,因此您可以通过适当的强制转换或转换来尝试猜测内存地址。但是,如果您尝试积极使用语言规范,则不会授予任何一致的行为。这意味着不同的编译器可以表现出不同的行为,并且可以更好地优化它们以更好地尊重它们所针对的真实机器。
你是什么意思,右值确实有一个地址。曾经尝试过
Type const value& = rvalue;
Type const* address = &value;
简单拿下这个案例
int a = 1 + 2;
1+2 被解析为 3。
问你自己:
- 3是一个对象吗?
- 3 将位于内存中的哪个位置?
当你需要一个对象的地址时,你使用 &。
如果右值是可寻址的,这意味着您可以声明一个指针,指向您的计算机决定存储的位置 3
int* a = &3;
这看起来对吗?:)