什么是Rust中的左值上下文?

时间:2017-02-18 06:17:37

标签: rust type-inference

根据the documentation,我们有左值和左值上下文。如何知道表达式是否在左值上下文中?它只是在作业中的表达方面确定了吗?

更具体一点,我需要了解何时使用Deref取消引用以及何时使用Index?与IndexMutmobno:{ type:String, unique:true, validate: { validator: function(v) { return /^([0-9]{10}$)/.test(v); }}, required: true } 相同。

2 个答案:

答案 0 :(得分:5)

你在这里问两个不同的问题。

  

更具体一点,我需要了解,当DerefMut用于取消引用时以及何时使用Deref时?与IndexIndexMut相同。

这仅取决于结果值是否可变使用。使用属于这些特征([]*)的运算符的表达式始终是左值表达式

现在你的问题更加复杂:

  

如果表达式位于左值上下文中,我怎么知道?它只是在作业中的表达方面确定了吗?

表达类别

回顾:什么是右值/左值表达式

  • 右值表达式表示
  • 左值表达式表示内存位置中的值(或者换句话说:表示生活在某处/有家的值)

哪些表达式是左值,哪些是右值表达式?只有少数 l 值表达式:

  • “names”(或更确切地说:路径)引用变量(本地,函数参数或静态)
  • 索引表达式(例如foo[3]
  • deref表达式(例如*foo
  • 字段访问表达式(例如foo.bar

上下文类别

rvalue / lvalue contexts 怎么样?这些上下文是表达式中的“槽”。例如,表达式“modulo”(%)有两个插槽,第一个和第二个操作数:⟨first⟩ % ⟨second⟩。现在这些背景有两种不同的风格:

  • 右值上下文是“插槽”,其中值是
  • 左值上下文是一个“广告位”,其中预计会有内存位置

那么哪个槽是右值,哪个是左值上下文?幸运的是,数字 l 值的上下文非常有限,所以这里有一个完整的列表:

  • (复合 - )作业的左侧(例如⟨lvalue context⟩ = ...;⟨lvalue context⟩ += ...;
  • 一元借款(&⟨lvalue context⟩&mut ⟨lvalue context⟩
  • 的操作数
  • 每当某些内容绑定到出现ref的模式时(例如let ref x = &⟨lvalue context⟩;

在上下文Y

中使用表达式X.

让我们看看我们可以在上下文中使用哪些表达式

    r [R in R] r 值表达式 > 值上下文:没问题,表达式用作值(例如,赋值右侧的文字3) 在 l [L in L] l 值表达式 > 值上下文:没问题,表达式用作内存位置(例如,赋值左侧的变量名) 在 r [L in R] l 值表达式 > 值上下文:由于上下文需要一个值而表达式表示“内存位置中的值”,我们只需使用表达式的值即可。所以:一切都很好(例如,作业右侧的变量名称)。所以我们可以看到:左值表达式 rvalue表达式更有价值。 在 l [R in L] r 值表达式 > 价值观背景:这就是问题所在。上下文需要内存地址,但表达式仅表示值。有时候,Rust会做一个“rvalue promotion”来制作像这样的工作。这意味着Rust会自动将表达式的值放入新的内存位置(临时变量)并在上下文中使用该位置。例如,&mut 3因为所述促销而起作用。此促销目前不适用于seems to be a bug in either the documentation or the compiler。的作业

答案 1 :(得分:1)

DerefMut / Deref / Index / IndexMut可变性决定,这与 lvalue / rvalue不同上下文即可。可变性对于右值上下文没有意义。

事实上,所有四个特征都要求操作数self位于左值上下文中,因为它们都以&Self&mut Self作为参数。

只要需要可变性,就会使用

DerefMut / IndexMut,例如

*here = ...;
here[i] = ...;

&mut here
&mut here[i]

here.call_some_mut_method(...)
here[i].call_some_mut_method(...)

左值上下文是您想要知道表达式的地址(内存位置/引用/ ...)而不是其值的位置。你需要一个左值的地方。

  

赋值或复合赋值表达式的左操作数是左值上下文,...

here = ...;

here += ...;
  

......这是一元借款的单一操作数。

&here

&mut here

let ref ... = here;
// Note: equivalent to `let ... = &here;`

let ref mut ... = here;
// Note: equivalent to `let ... = &mut here;`

注意:这显示了一个不可变的左值上下文

  

匹配表达式的判别式或主语可以是左值上下文,如果是ref绑定,则是rvalue上下文。

match here {
    Ok(ref ...) => ...,
    Err(ref mut ...) => ...,
}