Rust 中的左值上下文到底是什么? [英] What is exactly lvalue context in Rust?
问题描述
根据文档,我们有左值和右值上下文.我如何知道表达式是否在左值上下文中?是否仅由赋值中的表达式一侧决定?
According to the documentation, we have lvalue and rvalue contexts. How do I know if an expression is in an lvalue context? Is it determined just by the side of the expression in an assignment?
更具体地说,我需要了解何时使用 DerefMut
进行解引用,何时使用 Deref
代替?与 Index
和 IndexMut
相同.
To be more concrete, I need to understand when DerefMut
is used for dereferencing and when Deref
is used instead? Same with Index
and IndexMut
.
推荐答案
您在这里问了两个不同的问题.
You are asking two different questions here.
更具体地说,我需要了解,何时使用 DerefMut
进行解引用,何时使用 Deref
代替?与 Index
和 IndexMut
相同.
To be more concrete, I need to understand, when
DerefMut
is used for dereferencing and whenDeref
is used instead? Same withIndex
andIndexMut
.
这仅取决于结果值是否可变使用.使用属于这些特征([]
和 *
)的运算符的表达式总是左值表达式.
This only depends on whether or not the resulting value is used mutably or not. The expressions using the operators belonging to those traits ([]
and *
) are always lvalue expressions.
现在你的问题更复杂:
我怎么知道表达式是否在左值上下文中?是否仅由赋值中的表达式一侧决定?
How do I know, if an expression is in an lvalue context? Is it determined just by the side of the expression in an assignment?
表达类别
总结:什么是右值/左值表达式?
- 一个右值表达式代表一个值
- 一个左值表达式表示内存位置中的一个值(或者换一种说法:表示一个住在某处/有一个家的值)
- an rvalue expression represents a value
- an lvalue expression represents a value in a memory location (or in different words: represents a value which lives somewhere/has a home)
哪些表达式是左值,哪些是右值表达式?只有几个l值表达式:
Which expressions are lvalue and which are rvalue expressions? There are only a few lvalue expressions:
- 名称"(或者更确切地说:路径)引用变量(局部、函数参数或静态)
- 索引表达式(例如
foo[3]
) - deref 表达式(例如
*foo
) - 字段访问表达式(例如
foo.bar
)
右值/左值上下文怎么样?这些上下文是表达式中的槽".例如,表达式模"(%
)有两个这样的槽,第一个和第二个操作数:⟨first⟩ % ⟨second⟩
.现在这些上下文也有两种不同的风格:
What about rvalue/lvalue contexts? These contexts are "slots" inside of expressions. For example, the expression "modulo" (%
) has two of those slots, the first and the second operand: ⟨first⟩ % ⟨second⟩
. Now these contexts come in two different flavours as well:
- 右值上下文是一个槽",其中期望值
- 左值上下文是一个槽",其中需要一个内存位置
- an rvalue context is a "slot" where a value is expected
- an lvalue context is a "slot" where a memory location is expected
那么哪些插槽是右值,哪些是左值上下文?幸运的是,l值上下文的数量非常有限,所以这里是一个完整的列表:
So which slots are rvalue and which are lvalue contexts? Luckily, the number lvalue contexts is very limited, so here is a full list:
- (复合)赋值的左侧(例如
⟨lvalue context⟩ = ...;
或⟨lvalue context⟩ += ...;
) - 一元借用的操作数(
&⟨lvalue context⟩
and&mut ⟨lvalue context⟩
) - 每当某些东西被绑定到一个出现
ref
的模式时(例如let ref x = &⟨lvalue context⟩;
)
- the left hand side of a (compound-)assignment (e.g.
⟨lvalue context⟩ = ...;
or⟨lvalue context⟩ += ...;
) - the operand of an unary borrow (
&⟨lvalue context⟩
and&mut ⟨lvalue context⟩
) - whenever something is bound to a pattern in which a
ref
appears (e.g.let ref x = &⟨lvalue context⟩;
)
让我们看看我们可以在哪些上下文中使用哪些表达式:
Let's see which expressions we can use in which context:
- [R in R] r值表达在r值上下文:没问题,表达式用作值(例如赋值右侧的文字
3
) - [L in L] l价值表达在l价值上下文: 没问题,表达式用作内存位置(例如赋值左侧的变量名)
- [L in R] l值表达在r值上下文:由于上下文需要一个值,并且表达式表示内存位置中的值",我们可以只使用表达式的值.所以:一切都很好(例如,赋值右侧的变量名).所以我们可以看到:左值表达式比右值表达式更有价值.
- [R in L] r值表达在l值上下文: 这就是问题所在.上下文需要一个内存地址,但表达式只代表一个值.有时,Rust 会做一个右值提升"来使这样的情况起作用.这意味着 Rust 会自动将表达式的值放入一个新的内存位置(一个临时变量)并在上下文中使用该位置.例如,
&mut 3
由于上述促销而起作用.此促销目前不适用于 似乎是文档或编译器中的错误.
- [R in R] rvalue expression in rvalue context: no problem, the expression is used as value (e.g. the literal
3
on the right hand side of an assignment) - [L in L] lvalue expression in lvalue context: no problem, the expression is used as memory location (e.g. a variable name on the left hand side of an assignment)
- [L in R] lvalue expression in rvalue context: since the context requires a value and the expression represents a "value in a memory location" we can just use the value of the expression. So: it's all fine (e.g. a variable name on the right hand side of an assignment). So we can see: lvalue expressions are worth more than rvalue expressions.
- [R in L] rvalue expression in lvalue context: here is where it becomes problematic. The context requires a memory address, but the expression only represents a value. Sometimes, Rust will do an "rvalue promotion" to make situations like this work. This means that Rust will automatically put the value of the expression into a new memory location (a temporary variable) and use that location in the context. For example,
&mut 3
works because of said promotion. This promotion currently doesn't work for assignments, which seems to be a bug in either the documentation or the compiler.
这篇关于Rust 中的左值上下文到底是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!