23

ここに文書化された Rust の移動セマンティクスの優れた例があります: Rust By Example Web サイトのRust Move Semantics 。

私は両方のケースの基本的な理解を示しました。1 つ目は、プリミティブが新しい​​エイリアスを持つことができ、元のエイリアスを引き続き使用できる方法です。これは、最終結果がトレイトをi32利用していると見なされるコピーであるためです。Copyこれは私には理にかなっています。

i32さらに、多くの正当な理由により、2 番目の例は、ヒープ上のを参照する複数のエイリアスを持つという点で理にかなっています。Rust は所有権の規則を適用するため、新しいバインディングが作成されたので、元のエイリアスを使用することはできません。これにより、データ競合や二重解放などを防ぐことができます。

しかし、語られていない 3 番目のケースがあるようです。Rust は、トレイトを実装しないスタック割り当て構造体の移動をどのように実装しCopyますか? これを次のコードで示します。

#[derive(Debug)]
struct Employee{
    age: i32,
}

fn do_something(m: Employee){
    println!("{:?}", m);
}

fn main() {
    let x = Employee {
        age: 25,
    };

    do_something(x);

    //compiler error below because x has moved
    do_something(x);
}

これは私が知っていることです: 上記の場合、Rust は をEmployeestackに割り当てます。上記の構造体は特性を実装していないCopyため、新しいエイリアスに割り当てられたときにコピーされません。Employee構造体がスタックに割り当てられていて、トレイトを実装していない場合、どこCopyに/どのように移動するのでしょうか? do_something()のスタック フレームに物理的に移動しますか?

この難問を説明する上で、どんな助けも大歓迎です。

4

1 に答える 1

17

do_something()のスタック フレームに物理的に移動しますか?

はい。非型は、型​​とCopyまったく同じように物理的に移動されます。プリミティブ型が新しい場所 (新しいスタック フレームなど) にバイト単位でコピーされることは既に理解しています。CopymemcpyCopy

次に、次の実装を検討してBoxください。

struct Box<T> {
    ptr: *const T,
}

あなたが持っているとき

let b = Box::new(27i32);
do_something(b);    // `b` is moved into `do_something`

次に、i32Boxヒープに割り当てられ、そのヒープに割り当てられたメモリへの生のポインタが保存されます。Box直接 (内部の生のポインター) は、ヒープではなくスタックに直接あることに注意してください。ちょうどi32ヒープにあります。

Boxが移動すると、今memcpy言ったように ed になります。これは、スタックの内容がコピーされることを意味します(!!)...したがって、ポインターだけがバイト単位でコピーされます。i32!の 2 番目のバージョンはありません。

物理的に動くことに関しては、タイプCopyと非タイプの違いはありません。Copy唯一の違いは、コンパイラがこれらの型に異なる規則を適用することです。

于 2016-03-26T02:05:44.327 に答える