2016-03-26 6 views
8

Rustの移動セマンティクスの素晴らしい例がここに記載されています:Rust Move Semantics、Rust By ExampleのWebサイトRustはどのようにコピー可能ではないスタック変数を移動しますか?

私は両方のケースについて基本的な理解を示しています。最初のものはプリミティブが新しい​​エイリアスを持つ方法で、最終結果はi32というコピーがCopyの特性を利用するため、そのまま使用することができます。これは私には分かりやすい。

さらに、多くの理由から、2番目の例は、ヒープ上のi32を参照する複数のエイリアスを持つ点で意味があります。錆はオーナーシップルールを強制するため、新しいバインディングが作成されたので元のエイリアスを使用することはできません。これは、データ競合、二重解放などを防ぐのに役立ちます。

しかし、話されていない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); 
} 

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

この問題については、何か助けてください。

+1

あなたの例を単純化してもよろしいですか? 'Employee'構造体をあまり複雑でなくても、少なくとも生涯を削除するには素晴らしいでしょう。 'struct Employee {age:i32}'で十分でしょう。 –

+0

@LukasKalbertodt - はい私は例を単純化しました。 –

答えて

6

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

はい。非Copyタイプは、Copyタイプと同じように物理的に正確に移動されます:with memcpy。あなたはすでに、元のCopyタイプが新しい場所(新しいスタックフレームなど)にバイト単位でコピーされることを理解しています。

Boxのこの実装を検討してください:あなたは

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

を持っている場合

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

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

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

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

+4

少々:AIUI、値が実際に移動されるという保証はありませんが、セマンティクスはあなたがそうであると仮定しなければならないものです。例えば、コンパイラはビットをコピーするのを防ぐために 'do_something'を' b'への参照を受け入れるように自由に書き直すことができます。重要なことは、ビットが移動されたかのように*コードが動作することです。 – Shepmaster

関連する問題