字段访问表达式

field-expr.md
commit: 23672971a16c69ea894bef24992b74912cfe5d25
本章译文最后维护日期:2021-4-5

句法
FieldExpression :
   Expression . IDENTIFIER

*字段表达式(field expression)*是计算求取结构体联合体的字段的内存位置的位置表达式。 当操作数可变时,其字段表达式也是可变的。

*字段表达式(field expression)的句法规则为:一个被称为容器操作数(container operand)*的表达式后跟一个单点号(.),最后是一个标识符。 字段表达式后面不能再紧跟着一个被圆括号封闭起来的逗号分割的表达式列表(这种表示这是一个方法调用表达式)。 因此字段表达式不能是调用表达式的函数调用者。

字段表达式代表结构体(struct)联合体(union)的字段。要调用存储在结构体的字段中的函数,需要在此字段表达式外加上圆括号。

注意:如果要在调用表达式中使用它(来调用函数),要把此字段表达式先用圆括号包装成一个圆括号表达式

#![allow(unused)]
fn main() {
struct HoldsCallable<F: Fn()> { callable: F }
let holds_callable = HoldsCallable { callable: || () };

// 非法: 会被解析为调用 "callable"方法
// holds_callable.callable();

// 合法
(holds_callable.callable)();
}

示例:

mystruct.myfield;
foo().x;
(Struct {a: 10, b: 20}).a;
(mystruct.function_field)() // 调用表达式里包含一个字段表达式

自动解引用

如果容器操作数的类型实现了 DerefDerefMut(这取决于该操作数是否为可变),则会尽可能多次地自动解引用(automatically dereferenced),以使字段访问成为可能。 这个过程也被简称为自动解引用(autoderef)

借用

当借用时,结构体的各个字段以及对结构体的整体引用都被视为彼此分离的实体。 如果结构体没有实现 Drop,同时该结构体又存储在局部变量中,(这种各个字段被视为彼此分离的单独实体的逻辑)还适用于每个字段的移出(move out)。 但如果对 Box化之外的用户自定义类型执行自动解引用,这(种各个字段被视为彼此分离的单独实体的逻辑)就不适用了。

#![allow(unused)]
fn main() {
struct A { f1: String, f2: String, f3: String }
let mut x: A;
x = A {
    f1: "f1".to_string(),
    f2: "f2".to_string(),
    f3: "f3".to_string()
};
let a: &mut String = &mut x.f1; // x.f1 被可变借用
let b: &String = &x.f2;         // x.f2 被不可变借用
let c: &String = &x.f2;         // 可以被再次借用
let d: String = x.f3;           // 从 x.f3 中移出
}