3

基本的な (そしておそらくばかげた) 所有権に関する質問があります。内にラップされた&strfrom値のベクトルを作成しようとしています。中間変数を使用して抽出/ラップ解除を格納していますが、借用チェッカーを満たすために、ベクトルの前にこの中間変数を定義する必要があるようです:StringSome(String)String

作業コード:

fn main() {
    let a = Some("a".to_string());

    let mut val = String::new();
    let mut v = Vec::<&str>::new();

    if a.is_some() {
        val = a.unwrap();
        v.push(&val[..]);
    }
    println!("{:?}", val);
}

非動作コード:

fn main() {
    let a = Some("a".to_string());

    let mut v = Vec::<&str>::new();
    let mut val = String::new();

    if a.is_some() {
        val = a.unwrap();
        v.push(&val[..]);
    }
    println!("{:?}", val);
}

そしてコンパイラエラー:

<anon>:9:17: 9:20 error: `val` does not live long enough
<anon>:9         v.push(&val[..]);
                        ^~~
<anon>:4:35: 12:2 note: reference must be valid for the block suffix following statement 1 at 4:34...
<anon>:4     let mut v = Vec::<&str>::new();
<anon>:5     let mut val = String::new();
<anon>:6 
<anon>:7     if a.is_some() {
<anon>:8         val = a.unwrap();
<anon>:9         v.push(&val[..]);
        ...
<anon>:5:32: 12:2 note: ...but borrowed value is only valid for the block suffix following statement 2 at 5:31
<anon>:5     let mut val = String::new();
<anon>:6 
<anon>:7     if a.is_some() {
<anon>:8         val = a.unwrap();
<anon>:9         v.push(&val[..]);
<anon>:10     }
        ...
error: aborting due to previous error
playpen: application terminated with error code 101

遊び場コード

val問題は、ベクトルの前に変数を定義する必要があるのはなぜvですか? 私が見ているように、valスコープはスコープと同じvですか、それとも何か不足していますか?

4

1 に答える 1

3

バインディングは宣言の逆順で削除されます。つまり、最後に宣言されたものが最初に破棄されます。具体的には、動作しないコードでは、 のデストラクタが のデストラクタのval前に実行されvます。何が行われるかを慎重に検討しないと、これは安全ではありません。たとえば、派生元の がすでに破棄されてVec<&str>::drop()いるにもかかわらず、含まれる文字列スライスの内容を調べようとする可能性があります。String

Vec実際にはそうしませんが、他の正当なタイプはそれらの線に沿って何かをします. Drop以前は、ライフタイム/借用ポインターを含む型を安全に実装することは不可能でした。比較的最近の変更により、これらの追加の制限が導入されて安全になりました。

宣言するlet v, val;let val, v;、後で代入する場合、2 つのバインディング同じ有効期間を持つため、同じ有効期間の 2 つの変数を持つことは不可能ではないことに注意してください。

于 2015-03-06T12:57:31.160 に答える