【问题标题】:How is my reference to a struct member still valid after the struct was moved?移动结构后,我对结构成员的引用如何仍然有效?
【发布时间】:2016-09-20 05:25:41
【问题描述】:

我正在使用函数(名为 get)创建对结构成员的引用,然后使用另一个函数(名为 pr)移动该结构,然后取消引用之前创建的指针。

我在这里错了吗(也就是意外工作),还是我的参考根据某些规则仍然有效?

struct MyStruct {
    inner: i32,
}

fn get(a: &MyStruct) -> &i32 {
    return &a.inner;
}

fn pr(a: MyStruct) {
    println!("MyStruct {}", a.inner);
}

fn main() {
    println!("Hello, world!");
    let x = MyStruct { inner: 3 };
    let &i = get(&x);
    pr(x);
    println!("i {}", i);
}

Rust playground 输出:

Hello, world!
MyStruct 3
i 3

【问题讨论】:

  • 我还不是 Rust 专家(我正在研究它..)。但是,变量名称前的 & 号不正确。也就是说,导致它起作用的原因。如果您将其更改为 let i = get(&x);,则会返回 &i32,并且编译器会因为移动而正确出错,正如您所期望的那样。 TLDR:我不确定为什么 variable name 上的 & 号会导致它起作用。我也可能只是忘记了一些基本的东西……所以(耸耸肩)。
  • 在 Rust 中,&foo 是一个引用*const foo 是一个原始指针。我已更新您的文本以匹配您的代码。

标签: rust ownership


【解决方案1】:

let 表达式得到模式匹配并且

let &i = get(&x); // i.e. a &i32

导致i 被分配给i32,并且由于i32 是可复制的,因此不存在所有权冲突。

Rust 参考指出“let 语句引入了一组新的变量,由模式给出”(source)和“模式由文字、解构数组或枚举构造函数、结构和元组、变量绑定规范”(source)。

绑定的左侧,&i 不仅仅是一个文字,它告诉编译器它应该尝试与右侧的表达式进行模式匹配。在这种情况下,它会导致 i 指向可复制值 (i32) 而不是引用 (&i32)。换句话说:

let &i = get(&x);

等价于

let i = *get(&x);

所以x 没有被借用,pr(x) 仍然适用。

【讨论】:

  • 这是我的假设,但我只能找到对这种可能性的模糊参考。你有任何参考资料吗?我真的很难找到可以解释这一点的东西。
  • @SimonWhitehead 不幸的是,section on destructuring 对此并不明确。但由于i 的类型是i32(无引用),因此必须移动或复制它。您可以通过将i32 替换为不可复制的东西来测试它是否正常工作,例如一些新的结构Int(我刚刚这样做了)。
  • @starblue 我知道可复制和不可复制类型的基本原理是如何工作的。我不明白为什么变量绑定是模式匹配然后“就地”解构的。知道这一点使得可复制的推理完全有效......但是我们如何才能达到这种模式匹配的情况呢?我是否完全忽略了您可以在没有 match 关键字的 let 绑定中进行模式匹配?如果是这样.. 我遇到的几乎所有 Rust 材料似乎都跳过了。
  • @SimonWhitehead:想到了let (v1, v2, result) = uglyfunction(v1, v2)。这是 ownership 部分末尾的示例,就在 borrowing 之前。
猜你喜欢
  • 2022-11-07
  • 1970-01-01
  • 2019-04-15
  • 2022-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-20
  • 2021-08-25
相关资源
最近更新 更多