11

コピーできない型と、それを消費して(おそらく)生成する関数があります。

type Foo = Vec<u8>;

fn quux(_: Foo) -> Option<Foo> {
    Some(Vec::new())
}

ここで、概念的に に非常に似ている型を考えてみましょうBox

struct NotBox<T> {
    contents: T
}

NotBoxの内容を一時的に移動し、何かを戻す前に戻す関数を作成できます。

fn bar(mut notbox: NotBox<Foo>) -> Option<NotBox<Foo>> {
    let foo = notbox.contents; // now `notbox` is "empty"
    match quux(foo) {
        Some(new_foo) => {
            notbox.contents = new_foo; // we put something back in
            Some(notbox)
        }
        None => None
    }
}

esで動作する類似の関数を書きたいのですBoxが、コンパイラはそれを好みません:

fn baz(mut abox: Box<Foo>) -> Option<Box<Foo>> {
    let foo = *abox; // now `abox` is "empty"
    match quux(foo) {
        Some(new_foo) => {
            *abox = new_foo; // error: use of moved value: `abox`
            Some(abox)
        }
        None => None
    }
}

代わりに戻ることもできSome(Box::new(new_foo))ますが、それは不必要な割り当てを実行します-私はすでにいくらかのメモリを自由に使用できます! それを避けることは可能ですか?

私もステートメントを取り除きたいのですmatchが、コンパイラーはそれに満足していません(NotBoxバージョンであっても):

fn bar(mut notbox: NotBox<Foo>) -> Option<NotBox<Foo>> {
    let foo = notbox.contents;
    quux(foo).map(|new_foo| {
        notbox.contents = new_foo; // error: capture of partially moved value: `notbox`
        notbox
    })
}

それを回避することは可能ですか?

4

3 に答える 3

13

つまり、a からの移動Boxは特殊なケースです。

このstd::memモジュールは、Rust のメモリの安全性に穴 (!) を突っ込むことなく、値を移動するための多くの安全な関数を提供します。ここで興味深いのはswap、次のreplaceとおりです。

pub fn replace<T>(dest: &mut T, src: T) -> T

次のように使用できます。

fn baz(mut abox: Box<Foo>) -> Option<Box<Foo>> {
    let foo = std::mem::replace(&mut *abox, Foo::default());

    match quux(foo) {
        Some(new_foo) => {
            *abox = new_foo;
            Some(abox)
        }
        None => None
    }
}

mapを借用しないため、次の場合にも役立ちますBox

fn baz(mut abox: Box<Foo>) -> Option<Box<Foo>> {
    let foo = std::mem::replace(&mut *abox, Foo::default());

    quux(foo).map(|new_foo| { *abox = new_foo; abox })
}
于 2016-07-15T16:24:42.867 に答える