rust - 有没有一种安全的方法可以从 Rust 中的可变引用中临时检索拥有的值?

标签 rust unsafe ownership

<分区>

我正在使用两个独立的函数。

  • 第一个接受一个结构的拥有实例然后返回它。
  • 第二个采用可变引用但需要使用第一个函数。
// This structure is not `Clone`.
struct MyStruct;

fn take_owned(s: MyStruct) -> MyStruct {
    // Do things
    s
}

fn take_mut(s: &mut MyStruct) {
    *s = take_owned(s /* problem */);
}

我想过一个解决方案,但我不确定它是否合理:

use std::ptr;

// Temporarily turns a mutable reference into an owned value.
fn mut_to_owned<F>(val: &mut MyStruct, f: F)
where
    F: FnOnce(MyStruct) -> MyStruct,
{
    // We're the only one able to access the data referenced by `val`.
    // This operation simply takes ownership of the value.
    let owned = unsafe { ptr::read(val) };

    // Do things to the owned value.
    let result = f(owned);

    // Give the ownership of the value back to its original owner.
    // From its point of view, nothing happened to the value because we have
    // an exclusive reference.
    unsafe { ptr::write(val, result) };
}

使用这个函数,我可以做到:

fn take_mut(s: &mut MyStruct) {
    mut_to_owned(s, take_owned);
}

这段代码合理吗?如果没有,是否有安全的方法?

最佳答案

有人已经在名为 take_mut 的箱子中实现了您正在寻找的东西.

Function take_mut::take

pub fn take<T, F>(mut_ref: &mut T, closure: F) 
where
    F: FnOnce(T) -> T, 

Allows use of a value pointed to by &mut T as though it was owned, as long as a T is made available afterwards.

...

Will abort the program if the closure panics.

Function take_mut::take_or_recover

pub fn take_or_recover<T, F, R>(mut_ref: &mut T, recover: R, closure: F) 
where
    F: FnOnce(T) -> T,
    R: FnOnce() -> T, 

Allows use of a value pointed to by &mut T as though it was owned, as long as a T is made available afterwards.

...

Will replace &mut T with recover if the closure panics, then continues the panic.

实现基本上就是您所拥有的,加上所描述的 panic 处理。

关于rust - 有没有一种安全的方法可以从 Rust 中的可变引用中临时检索拥有的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66597738/

相关文章:

rust - 如何将 `quick-error` 与盒装错误类型一起使用?

rust - 带有运行时定义成员的标记联合

rust - Substrate - 在此范围内找不到类型 `Vec`

rust - 拆分 `Vec`

rust - 不可变值仍在移动

memory-management - 不可变的字符串和克隆

regex - 如何在没有 Cargo 的情况下在 Rust 中使用正则表达式?

python - 无需执行即可从文件中读取列表和字典

c# - 为什么这个 byte* 和 uint 的加法不能进位到更高的 dword 中?

error-handling - 无法将io::Error从可见结果中移出