さびストリング対


なぜ錆には異なる文字列があるのでしょうか
私はこれらの質問を別の方法でオンラインでポーズを見てきたし、それは本当のRust ' sString and &str タイプは、特にダイナミックなプログラミング言語に精通しているさびに新しい人々のために混乱させることができます.それで、2つのストリングタイプについて話しましょう、そして、我々が混乱のいくらかを片づけることができるならば、見てください.
それは結局意味をなします、そして、さびは本当に両方のタイプを必要とします.それらは全く異なり、異なるユースケースがあります.

TLドクター
それは、「誰が記憶を所有しているか」についてのすべてです.

文字列
  • String メモリに文字列を含み、メモリを所有します.
  • 用途String 関数内で作成された文字列を返します.
  • あなたがいるならばString あなたはそれに変換するために参照を渡すことができます&str .

  • とstr
  • &str は別の文字列(スライス)へのリファレンスですが、メモリを所有しません.
  • 好む&str ストリングスライスを受け入れて、それを明らかにするfunction引数では、ストリングは変異しません.
  • あなたがいるならば&str そして、新しいString のいずれかをクローン化することができますto_owned() or to_string() (それらは効果的に同じです-あなたのコードが読んで、一貫しているのをより明確にします).これらはメモリをコピーし、新しいものを作るでしょうString .

  • それは記憶と所有権についてです
    第一に、私たちは、錆が記憶を管理する方法について少し話をする必要があります.私はこの短いを維持しようとしますが、それは非常に重要なときに我々はString and &str .
    ご存知のように、錆はガベージコレクターを持っていません.つまり、コンパイラは、コード内の特定の点でメモリを明示的に割り当てたり解放したりする必要があり、メモリが安全に取り除かれるように、何かがもはや使われていないときに決定するメカニズムを必要とします.
    さびの中のこのメカニズムは「所有」(「借入」)と呼ばれています.次のコードを考えます.
    fn main() {
        let owned_string = get_string();
        print_string(&owned_string);
    }
    
    fn get_string() -> String {
        let s = String::from("Hello, World!");
        // In Rust we return s by omitting the semicolon
        s
    }
    
    fn print_string(my_string: &str) {
        println!("{}", my_string);
    }
    
    
    こちらでget_string() ヒープ上の文字列に対するメモリの割り当てを行います.ヒープがどのようなものかを知るために.see here ) 変数に代入しますs . この時点で我々は言うことができるs そのメモリを所有している.錆コンパイラは、現在の範囲を追跡しますs ためには、いつそれを解雇を知っている.これはs 範囲外であるs 代わりに“移動”(あなたは所有権の移転のように考えることができる)です.上記の場合s 実際には、変数owned_string トップで.
    get_string() 返信、メモリがコピーされず、どこにも行かない.むしろ、そのメモリの所有権は、今度は呼び出し元に転送されるowned_string ).
    錆コンパイラは、この新しい所有者を追跡するowned_string ためにいつの場所を見つけるのを知っている.この場合、main() 関数.
    エーString これまで1オーナーだけです.その所有者は、他の人が一時的に「借りる」ことを許すprint_string(&owned_string); ) , しかし、メモリがスコープの外に出たときにメモリが解放されます.

    借入と引用
    では、他の関数を見てみましょう.
    fn print_string(my_string: &str) {
        println!("{}", my_string);
    }
    
    The & シンボルとはstr (文字列スライス).ほとんど使用しないでしょうstr なしで& それで、それをちょうど彼らと考えるほうが簡単です&str , または"文字列スライスへのリファレンス"です.
    考慮するString 以前は所有していた割り当てられたメモリを持っていた.私たちがその文字列(またはその一部)への参照をパスしたいのであれば、受信者にそれを変更させないでください.錆では、それを「不変の退屈」と呼びます& 手段.それは他の言語では“参照”のようですが、錆はさらに一歩行くと、その内容が変異(変更)することができますかどうか宣言することができます.
    上の例では&String の代わりに&str そして、私たちがとにかくストリング全体を通過したので、それはOKになりました.しかし、それは他の呼び出し元が部分文字列を通過させるのを許しませんString ). これは文字列スライス&str のほうがずっと便利です.&str は、固定長の文字列のメモリに直接ポインタである.あなたは、元のコードで行に気づくでしょうprint_string(&owned_string); . 私たちはString 関数の中に&str . これはString 型は自動的に&str - これは、既知の長さで非常に同じメモリへのポインタを返すだけです.&str はメモリを変更することはできません.
    実際には、錆は&str (スレッド間で)安全ですそれを保証することによって何もメモリを変更することができます& 参照変数はスコープ内です.錆も所有していることを保証しますString それが&str 参照がスコープ内に残っている間(参照していない場合は参照先が有効になっています).これらはあなたがここにそれを参照してくださいそこに文字列を作成する他の言語と遭遇する可能性のある厄介なバグのすべての種類を防ぐために錆のBorrowチェッカーの非常に強力な機能ですが、それは誤って元を変更する.

    文字列とstrの違いは・・・String メモリに文字列を保持し、メモリを所有します.&str は別の文字列へのリファレンスですが、それはメモリを所有しません.

    どちらかを使うとき
    一般に、使用String 構造体とenumでは、構造体またはenumにコンテンツを所有します.また、使用String 関数の中でその文字列が割り当てられた関数から文字列を返すときには、その関数が最後に参照を返すことはありません.
    好む&str 関数の引数に対してString 関数の所有権を放棄する(これはまれである傾向がある).

    最後の時間.
    用途String メモリを所有する必要がある場合は、たとえば関数の文字列を作成し、それを返す必要があります.
    用途&str あなたが別の所有しているメモリへの不変の参照を望むときString 変数(あるいはコードの文字列リテラル).