首页 文章

在旋转变量时,“无法移出变量,因为它是借用的”

提问于
浏览
6

我正在编写一个程序写入文件并旋转文件它似乎改变了文件,因为它是由我的struct借用的 . 即使我 drop 结构的实例,我似乎无法重新获得文件的所有权来重命名它 . 这是我的example

use std::fs::File;
use std::io::{Write};
use std::mem::{drop};

pub struct FileStruct<W: Write> {
    pub writer: Option<W>,
}

impl <W: Write> FileStruct<W> {
    pub fn new(writer: W) -> FileStruct<W> {
        FileStruct {
            writer: Some(writer),
        }
    }
}

fn main() {
    let mut file = File::create("tmp.txt").unwrap();
    let mut tmp = FileStruct::new(&mut file);
    loop {
        if true { //will be time based if check
            drop(tmp);
            drop(file);
            file = File::create("tmp2.txt").unwrap();
            tmp = FileStruct::new(&mut file);
        }
        // write to file
    }
}

我知道我可以通过将文件创建移动到 FileStructnew 函数调用而不是具有中间变量 file 来实现此工作,但我想知道为什么这个方法我强行删除所有变量引用的所有变量应该退回不起作用 .

2 回答

  • 3

    正如the std::mem::drop documentation所说,

    虽然这确实调用了参数的Drop实现,但它不会释放任何借用,因为借用是基于词法范围 .

    所以即使你打电话 drop ,仍然会借用 file .

  • 7

    删除 tmp 不"release the borrow" file 因为借用是词法范围的 . 只要程序执行在包含 tmp 的词法范围内,即使你删除它,它也是"active" . 如果/一旦支持"non-lexical scopes",您将来可能会做什么 . 在此之前,您可以使用 RefCell

    use std::cell::RefCell;
    use std::io::{ self, Write };
    
    /// wraps a reference to a RefCell<W>
    struct RefCellWriteRef<'a, W: 'a>(&'a RefCell<W>);
    
    /// implement Write for when W is Write
    impl<'a, W: Write + 'a> Write for RefCellWriteRef<'a, W> {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            let mut w = self.0.borrow_mut();
            w.write(buf)
        }
        fn flush(&mut self) -> io::Result<()> {
            let mut w = self.0.borrow_mut();
            w.flush()
        }
    }
    
    fn main() {
        let file: RefCell<Vec<u8>> = RefCell::new(Vec::new());
        // use RefCellWriteRef(&file) instead of &mut file
        let mut tmp = RefCellWriteRef(&file); 
        for iter in 0..10 {
            if iter == 5 {
                drop(tmp);
                file.borrow_mut().clear(); // like opening a new file
                tmp = RefCellWriteRef(&file);
            }
            tmp.write(b"foo").unwrap();
        }
        drop(tmp);
        println!("{}", file.borrow().len()); // should print 15
    }
    

    这里的诀窍是,给定对 RefCell<T> 的共享引用,你可以(最终)通过 borrow_mut() 获得 &mut T . 编译时借用检查器很高兴,因为我们只在表面上使用共享引用,并且可以像这样共享 file . 通过在运行时检查内部 T 是否已被可变地借用来避免可变别名 .

相关问题