6

我正在编写一个程序,该程序写入文件并不时旋转它正在写入的文件。当我检查旋转文件时,我似乎无法更改文件,因为它是由我的结构借用的。即使我drop是结构的实例,我似乎也无法重新获得文件的所有权来重命名它。这是我的例子

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
    }
}

我知道我可以通过将文件创建移动到new函数调用FileStruct而不是使用中间变量file来实现这一点,但我想知道为什么这种方法强制删除所有变量引用应该返回的所有变量不起作用。

4

2 回答 2

7

正如文件所说std::mem::drop

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

所以即使你打电话dropfile仍然会借来的。

于 2015-12-01T09:59:47.833 回答
3

删除tmp不会“释放借用”,file因为借用是词法范围的。只要程序执行在包含的词法范围内,它就是“活动的”,tmp即使你删除它也是如此。如果/一旦支持“非词法范围”,您打算做的事情将来可能会实现。在那之前,你可以让它工作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
}

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

于 2015-12-01T20:47:33.113 回答