Rust 对温度值的不可变和可变引用是如何删除的?

How are Rust immutable and mutable references to temp values dropped?

提问人:Andrei Nikolaenko 提问时间:4/15/2023 最后编辑:kmdrekoAndrei Nikolaenko 更新时间:9/16/2023 访问量:80

问:

首先,我知道有很多类似的问题,我读过很多讨论,但我仍然无法理解我的情况。

struct Test {
    x: u32,
}

fn main() {
    let mut t = & mut Test { x: 0 };
    println!("{}", t.x);
    t = & mut Test { x: 1 };
    println!("{}", t.x);
}

好的,这给出了预期的错误:

error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:8:15
  |
8 |     t = & mut Test { x: 1 };
  |               ^^^^^^^^^^^^^- temporary value is freed at the end of this statement
  |               |
  |               creates a temporary value which is freed while still in use

creates a temporary value which is freed while still in use– 没错,但为什么以前没有发生过这个错误?它只发生在 的第二次赋值上,而第一次赋值就没问题了。难道它不应该也创建一个被丢弃的临时值吗?这是我无法理解的。&mut

此外,如果我删除,那么一切正常:mut

fn main() {
    let mut t = & Test { x: 0 };
    println!("{}", t.x);
    t = & Test { x: 1 };
    println!("{}", t.x);
}

但是为什么?不可变的引用仍然是引用,它仍然指向某些数据,并且临时值仍会被删除。所以引用应该是无效的。也应该给出错误,但不,它没有。为什么?

但是等等,还有更多!如果我为以下对象实现特征:DropTest

impl Drop for Test {
    fn drop(& mut self) { }
}

现在我再次收到相同的错误,而无需更改 中的代码。它有什么关系?main()

临时 Rust 参考

评论

0赞 Andrei Nikolaenko 4/15/2023
@cafce25它离得很近。它可以解释为什么借用临时的是合法的。(答案:通过隐藏的中间体)。但它没有回答为什么它第一次工作而第二次不工作的问题(但是它会与显式 )。也没有回答为什么不可变的引用在任何时候都能正常工作的问题。所以我不知道,我需要更多阅读它。let tmp = ...let tmp = ...

答:

3赞 cafce25 4/15/2023 #1

为什么

let mut t = &mut Test { x: 0 };

作品在为什么借用临时的合法? 和参考文献中进行了描述:

语句中表达式的临时作用域有时会扩展到包含该语句的块的作用域。根据某些语法规则,当通常的临时范围太小时,就会这样做。letlet

t = &mut Test { x: 1 };

不起作用,因为它不是声明,因此没有资格获得相同的终身促销活动。let

let mut t = &Test { x: 0 };

允许将临时提升为静态(因为它是不可变的) 以下人员也有资格持续晋升

t = &Test { x: 1 };

所以它起作用了。

由于实现更改了静态变量与局部变量的语义,因此实现它的任何内容都不符合持续提升的条件,因此问题再次出现(对实现的事物的引用仅适用于与可变引用相同的范围扩展)。链接的参考文章包含对所有这些的更全面的解释。DropDrop

评论

0赞 Andrei Nikolaenko 4/15/2023
虽然我还没有完全理解,但我看到你的答案给出了正确的信息,我只是需要时间来掌握它。因此,我会将您的答案标记为答案,我可能会回来进一步澄清,以使我的问题和您的答案更有用。