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の代わりに関数呼び出しに移動することでこれを機能させることができることはわかっていますが、すべての変数参照が返される必要があるすべての変数を強制的にドロップするこのメソッドの理由を知りたいです動作しません。FileStructfile

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 への共有参照を指定すると、 (最終的に) via をRefCell<T>取得できることです。コンパイル時の借用チェッカーは、表面上で共有参照を使用するだけであり、そのように共有しても問題ないため、満足しています。内部がすでに可変的に借用されているかどうかを実行時にチェックすることにより、可変エイリアシングが回避されます。&mut Tborrow_mut()fileT

于 2015-12-01T20:47:33.113 に答える