rust - Rust 对临时值的不可变和可变引用是如何删除的?

标签 rust reference temporary

首先,我知道有很多类似的问题,我也阅读了很多讨论,但我仍然无法理解我的情况是怎么回事。

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

创建一个临时值,该值在仍在使用时被释放 - 这是正确的,但是为什么之前没有发生此错误?它仅发生在 &mut 的第二次分配上,而第一个则很好。难道它不应该创建一个被丢弃的临时值吗?这是我无法理解的地方。

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

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

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

但是等等,还有更多!如果我为 Test 实现 Drop 特征:

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

现在我再次遇到同样的错误,而没有更改 main() 中的代码。有什么关系吗?

最佳答案

为什么

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

作品描述于 Why is it legal to borrow a temporary?reference :

The temporary scopes for expressions in let statements are sometimes extended to the scope of the block containing the let statement. This is done when the usual temporary scope would be too small, based on certain syntactic rules.

t = &mut Test { x: 1 };

不起作用,因为它不是 let 语句,因此不符合相同的生命周期促销资格。

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

允许将临时变量提升为静态变量(因为它是不可变的) 并且以下内容符合 constant promotion 的资格,还有:

t = &Test { x: 1 };

这样就可以了。

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

关于rust - Rust 对临时值的不可变和可变引用是如何删除的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76022549/

相关文章:

c++ - 从常量引用初始化非常量引用

C++ 临时字符串生命周期

rust - 使用 Real-Time For the Mass 时未定义对 main 的引用

random - 获得与前一个不同的随机数的惯用方法?

rust - 如何在 Rust 中将 u16 的低/高 8 位转换为 u8?

Matlab,循环执行后自动删除索引变量

sql-server - 临时表 - 允许的最大行值数为 1000

generics - 为什么我不能在带有类型参数的特征上添加一揽子实现?

python - 删除列表列表中的共享引用?

C++ 通过 Const 引用传递并通过 Const 引用返回