Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 为什么要通过自动删除来访问引用变量?_Rust - Fatal编程技术网

Rust 为什么要通过自动删除来访问引用变量?

Rust 为什么要通过自动删除来访问引用变量?,rust,Rust,在这段代码之前,我想我已经有了移动语义的概念 fn main() { let v = Data { body: vec![10, 40, 30], }; p(&v); } fn p(d: &Data) { for i in d.body { // &d.body, Why d.body move? println!("{}", i); } } struct Data { b

在这段代码之前,我想我已经有了移动语义的概念

fn main() {
    let v = Data {
        body: vec![10, 40, 30],
    };
    p(&v);
}

fn p(d: &Data) {
    for i in d.body {
        // &d.body, Why d.body move?
        println!("{}", i);
    }
}

struct Data {
    body: Vec<i32>,
}
我传递了一个引用,并通过自动排序功能访问了一个字段,那么为什么这是一个移动?

此循环将:


如您所见,它正在使用
进入\u iter
,这将移动向量
d.body
您正在访问
d
中的字段
body
<代码>正文本身是一个
Vec
,它不是一个参考。如果要直接使用
d
,则无需使用
&
,但由于您要访问
d
中的字段,因此必须指定要引用该字段


基本上
d
拥有
body
。若你们借用
d
你们不能窃取
正文,它属于
d
,但你们可以借用它。

你们所做的是在指针上访问字段

检查:

如果点左侧的表达式类型是指针,则 根据需要自动取消引用多次,以使 现场访问是可能的

Rust如何对借用内容计算字段访问表达式的示例:

let d = Data { /*input*/}
let body = (&d).body // -> (*&d).body -> d.body
let ref_body = &(&d).body // -> &(*&).body -> &d.body -> &(d.body) 
注意:d仍然是借来的内容,只需自动排序即可访问字段


为什么要搬家? 考虑以下代码:

struct Data {
    body: Vec<i32>,
    id: i32,
}

fn p(mut d: &Data) {
    let id = d.id;
}
fn p(mut d: &Data) {
    let id = d.id; // works
    let body = d.body; // fails
}
此代码将不起作用,因为:

  • Rust将尝试复制
    d。body
    但是
    Vec
    没有实现
    copy
    特性
  • Rust将尝试从
    d
    移动
    正文
    ,您将得到“无法移出借用内容”错误 这对循环有什么影响? 从

    for
    表达式是一种语法结构,用于在
    std::iter::IntoIterator的实现提供的元素上循环

    for循环等效于以下块表达式

    'label: for PATTERN in iter_expr {
        /* loop body */
    }
    
    相当于

    {
        let result = match IntoIterator::into_iter(iter_expr) {
            mut iter => 'label: loop {
                let mut next;
                match Iterator::next(&mut iter) {
                    Option::Some(val) => next = val,
                    Option::None => break,
                };
                let PAT = next;
                let () = { /* loop body */ };
            },
        };
        result
    }
    
    这意味着您的向量必须具有
    IntoIterator
    的实现,因为
    IntoIterator::into_iter(self)
    需要
    self
    作为参数。幸运的是,两者都存在

    为什么会发生这种情况? 简单地说:

    • 当您使用
      &d.body
      时,您的循环使用
      &Vec
      实现
      IntoIterator
    此实现返回指向向量切片的迭代器。这意味着您将从向量中获得元素的引用

    • 使用
      d.body
      时,循环使用
      IntoIterator的
      Vec
      实现

    这个实现返回一个迭代器,它是一个使用迭代器。这意味着您的循环将拥有实际元素的所有权,而不是它们的引用。对于消费部分,此实现需要实际向量而不是引用,因此会发生移动。

    这并不能解决当
    d
    是引用时
    d.body
    移动的原因。如果直接使用
    d
    ,则不需要
    &
    ,但因为您正在访问
    d
    中的字段,您必须指定希望引用该字段。-这个答案并没有描述为什么会发生这种情况。
    {
        let result = match IntoIterator::into_iter(iter_expr) {
            mut iter => 'label: loop {
                let mut next;
                match Iterator::next(&mut iter) {
                    Option::Some(val) => next = val,
                    Option::None => break,
                };
                let PAT = next;
                let () = { /* loop body */ };
            },
        };
        result
    }