Rust:使用drop(&RefMut)而不是drop(RefMut)?

huangapple go评论61阅读模式
英文:

Rust : drop(&RefMut) instead of drop(RefMut)?

问题

我知道当从 RefCell 中借用一个值时,我可以手动丢弃它以结束这个借用。

然而,如果我使用对 RefMut 的引用而不是直接使用 RefMut,似乎无法使用 drop 特性来结束这个借用。

那么,尝试丢弃 &RefMut 会发生什么?为什么在这个操作中 RefMut 不会被丢弃?如果引用的 RefMut 没有被丢弃,那么什么时候会被丢弃?

use std::cell::RefCell;

struct Data {
    pub x: usize,
}

fn main() {
    let c = RefCell::new(Data { x: 42 });
    let b = &c.borrow_mut();
    drop(b);
    let mut d = c.borrow_mut();
    d.x = 43;
    println!("Hello, world!");
}

输出:

thread 'main' panicked at 'already borrowed: BorrowMutError', src/main.rs:11:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
英文:

I know when borrowing a value from a RefCell, I can manually drop it to end this borrow.

However, if I use the reference to a RefMut instead of directly using the RefMut, the drop trait seems invalid to end this borrow.

So, what happend when trying to drop the &RefMut ? and why the RefMut will not be dropped during this operation. If the referenced RefMut is not dropped, when will it be dropped ?

use std::cell::RefCell;

struct Data {
    pub x: usize,
}

fn main() {
    let c = RefCell::new(Data { x: 42 });
    let b = &c.borrow_mut();
    drop(b);
    let mut d = c.borrow_mut();
    d.x = 43;
    println!("Hello, world!");
}

output

thread 'main' panicked at 'already borrowed: BorrowMutError', src/main.rs:11:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

答案1

得分: 3

References 只有在它们引用的值在某处也存在时才能存在。在 C/C++ 中,如果创建一个指向临时变量的引用但未将其存储在变量中,这将是未定义的行为。然而,在 Rust 中,这是合法的,会在后台创建一个不可见的变量,其生存周期延续至当前作用域的结束。这被称为临时生命周期扩展。更多信息可以在这里找到。

你可以通过引入另一个作用域来限制它的生命周期:

use std::cell::RefCell;

struct Data {
    pub x: usize,
}

fn main() {
    let c = RefCell::new(Data { x: 42 });
    {
        let b = &c.borrow_mut();
        drop(b);
    }
    let mut d = c.borrow_mut();
    d.x = 43;
    println!("Hello, world!");
}

或者将它存储在一个命名变量中来限制它的生命周期:

use std::cell::RefCell;

struct Data {
    pub x: usize,
}

fn main() {
    let c = RefCell::new(Data { x: 42 });

    let b_val = c.borrow_mut();
    let b = &b_val;
    drop(b);
    drop(b_val);

    let mut d = c.borrow_mut();
    d.x = 43;
    println!("Hello, world!");
}
英文:

References can only exist if the value they reference also exists somewhere. In C/C++ it would be undefined behaviour to create a reference to a temporary that doesn't get stored in a variable. In Rust, however, it is legal, and an invisible variable gets created in the background that lives until the end of the current scope. This is called temporary lifetime extension. More info can be seen here.

You can limit its lifetime by introducing another scope:

use std::cell::RefCell;

struct Data {
    pub x: usize,
}

fn main() {
    let c = RefCell::new(Data { x: 42 });
    {
        let b = &c.borrow_mut();
        drop(b);
    }
    let mut d = c.borrow_mut();
    d.x = 43;
    println!("Hello, world!");
}
Hello, world!

Or by storing it in a named variable instead:

use std::cell::RefCell;

struct Data {
    pub x: usize,
}

fn main() {
    let c = RefCell::new(Data { x: 42 });

    let b_val = c.borrow_mut();
    let b = &b_val;
    drop(b);
    drop(b_val);

    let mut d = c.borrow_mut();
    d.x = 43;
    println!("Hello, world!");
}
Hello, world!

huangapple
  • 本文由 发表于 2023年5月7日 17:13:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193040.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定