2016-07-11 9 views
3

私は、コンパイラが、それはErrorのためのコピーコンストラクタを生成できないと文句を言いよう文字列を含むコピー可能な構造体を定義するには?

#[derive(Copy, Clone)] 
enum Command { 
    Quit, 
    Error { msg: String }, 
} 

のような構造体を持っています。

構造体をコピー可能にして、チャネルを別のスレッドに渡す必要があります。

error: the trait `Copy` may not be implemented for this type; variant `Error` does not implement `Copy` [E0205] 
#[derive(Copy, Clone)] 
^~~~~~~~~~~~~~~~~~~~~~ 
note: in this expansion of #[derive_Copy] (defined in src/main.rs) 

msgi32ある場合はコンパイルされます。そのような基本的な タイプがStringとコピーできないと奇妙に思えます。

+0

'String'は' Vec'と同じように 'Copy'できません。どちらもヒープ割り当てコンテンツを扱うので、 'memcpy'を使って安全にコピーすることはできません。本の関連ページ:https://doc.rust-lang.org/book/strings.html –

+0

私は見ていますが、私はオブジェクトをチャンネルに渡す必要があり、コピー可能なタイプが必要です。私はこのチュートリアルをカバーからカバーまで読んでいますが、それは浅いものです。 –

+2

@ DaneelS.Yaitskovタイプは、チャネルを通過するためにコピー可能である必要はありません。 –

答えて

7

私にとっては、文字列などの基本的なタイプはコピーできません。

錆は明示的です。

Cのプログラマー(そして最も顕著なのはLinus Torvald)からC + +に関してよく聞かれていることの1つは、メモリ割り当てを隠すC++での暗黙的なコピーが多すぎるということです。暗黙のコンバージョンと組み合わせると、予想外の場所で実際に変わる可能性があります。

代わりに、Rustは基本的な操作の複雑さを明らかにする意図で設計されています。暗黙的にいくつかの変換を実行します(&Tから&Traitまで)。ただし、は安い(一般的には一定の時間)です。

この明示は2つの特性に示して、あなたはここにある:

  • Cloneは、新しいインスタンスを作成する方法をを示す程度であり、明示的に呼び出す必要があります。ほとんどのタイプ(ただしすべてではありません)は、それを使用してコピーできます。

  • Copyは、開発者がタイプの暗黙コピーをアクティブにしたいことを示す特定のコンパイラ特性です。

    • String:浅いコピーが何のメモリ割り当てがあなたの発言を確実にするために、

    だから、それらの暗黙のコピーの一部として発生しないことが保証され、ディープコピーと同等である場合にのみ使用可能ですそれは非自明なメモリ割り当てが発生してしまうためコピー可能で、.clone()

  • Stringが暗黙的にコピーできません使用
3

Stringは、事実上、ヒープ割り当てされたデータへのポインタであり、長さと容量です。その情報をコピーすると、所有する2つの変数が作成され、両方とも同じヒープ割り当てデータを指しているため、Rustのメモリ管理が損なわれます(use-after-free問題に陥る)。あなたの構造体は、チャネルを介して送信されるCopyを実装する必要はありません、と述べた

、それだけで(ポインタのサイズはコンパイラに知られているので)Stringがある、Sizedする必要があります。 Stringの構造体または列挙型を送信すると、その特性を引き出す必要なく、すぐに使用できます。

関連する問題