rust - 暂时搬出借用的内容

标签 rust ownership borrow-checker

我正在尝试替换可变借用中的值;将它的一部分移动到新值中:

enum Foo<T> {
    Bar(T),
    Baz(T),
}

impl<T> Foo<T> {
    fn switch(&mut self) {
        *self = match self {
            &mut Foo::Bar(val) => Foo::Baz(val),
            &mut Foo::Baz(val) => Foo::Bar(val),
        }
    }
}

上面的代码不起作用,这是可以理解的,将值移出 self 会破坏它的完整性。但由于该值随后立即被删除,我(如果不是编译器)可以保证它的安全。

有什么办法可以实现吗?我觉得这是针对不安全代码的工作,但我不确定它会如何工作。

最佳答案

mem:uninitialized自 Rust 1.39 以来已被弃用,取而代之的是 MaybeUninit .

然而,这里不需要未初始化的数据。相反,您可以使用 ptr::read 获取 self 引用的数据。

此时,tmp 拥有枚举中数据的所有权,但如果我们要删除 self,该数据将尝试由析构函数读取,导致内存不安全。

然后我们执行转换并将值放回原处,恢复类型的安全性。

use std::ptr;

enum Foo<T> {
    Bar(T),
    Baz(T),
}

impl<T> Foo<T> {
    fn switch(&mut self) {
        // I copied this code from Stack Overflow without reading
        // the surrounding text that explains why this is safe.
        unsafe {
            let tmp = ptr::read(self);
    
            // Must not panic before we get to `ptr::write`

            let new = match tmp {
                Foo::Bar(val) => Foo::Baz(val),
                Foo::Baz(val) => Foo::Bar(val),
            };
    
            ptr::write(self, new);
        }
    }
}

此代码的更高级版本将防止 panic 从这段代码中冒出,而是导致程序中止。

另见:

关于rust - 暂时搬出借用的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29570781/

相关文章:

compilation - 我不明白借贷是如何运作的

rust - 是否可以在运行时组合函数链?

rust - 改变闭包体中的变量

rust - 指向带有生命周期参数的方法的函数指针的类型

rust - 难以理解 Rust 借用系统

recursion - 为什么我不需要显式借出一个借来的可变变量?

scope - C++ 的 shared_ptr 在 Rust 中的等价物是什么?

rust - 引用上的Rust调用方法

rust - 无法编译允许将值插入其中的 OneOrMany 枚举

rust - 借用检查器没有意识到 `clear` 丢弃了对局部变量的引用