web-dev-qa-db-ja.com

価値が十分に長生きしない

ライフタイムは完全には理解していませんが、bのライフタイムはselfの前に終了すると思います。

では、このコードを編集するにはどうすればよいですか?メモリに何かをコピーしますか?新しいインスタンスを作成する場合、この存続期間はこのケースに準拠する必要があります。

pub struct Formater {
    layout: &'static str,
}

impl Formater {
    pub fn new(layout: &'static str) -> Formater {
        let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
        let b = regex.replace_all(layout, "{}");

        return Formater {
            layout: &b,
        };
    }
}

エラー:

error: `b` does not live long enough
  --> src/format.rs:16:22
   |
16 |             layout: &b,
   |                      ^ does not live long enough
17 |         };
18 |     }
   |     - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...
10
彭灵俊

bのスコープはnew関数であるため、関数が戻るとそのメモリは解放されます。しかし、その関数からbへの参照を返そうとしています。 Rustこれを許可すると、その参照を使用する可能性のある唯一のコードはそれを使用することになりますafter値は無効です。借用チェッカーがあなたを保護しています- 未定義の動作

layoutを_&'static str_にすることは、物事を単純にしているように聞こえますが、_regex.replace_all_から動的に割り当てられたメモリが静的であると期待するのは無理です。 unsafeコードに入らない場合は、_'static_の有効期間内のすべてをコンパイル時の定数と見なす必要があります。たとえば、文字列リテラル。

他の人が言っているように、おそらくlayoutStringにしたいと思うでしょう。 Stringは_&str_に似ていますが、owns基になるstrです。つまり、Stringを移動すると、基になるstrも一緒に移動します。 _&str_は参照であり、それが指すstrの所有者よりも長生きしてはなりません。


本当に_&str_にしたい場合は、new()の呼び出し元に_&str_を所有させ、それを可変参照として渡すこともできますが、人間工学的ではありません。

_pub struct Formatter<'a> {
    layout: &'a str,
}

impl <'a> Formatter<'a> {
    pub fn new(layout: &'a mut &str) -> Formatter<'a> {
        let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
        *layout = regex.replace_all(layout, "{}");

        return Formatter {
            layout: layout,
        };
    }
}
_

これにより、問題がコールスタックの1層上に移動し、newに渡す参照がnewによって変更されます。

_pub fn main() {
    let mut s = "blah %{blah}";
    {
        let formatter = Formatter::new(&mut s);
        println!("{:?}", formatter.layout); // "blah {}"
    }
    println!("{:?}", s); // "blah {}"
}
_

現在、smainが所有しているため、formatterは、mainよりも小さいスコープでのみ使用される限り有効です。

しかし、全体として、この方法は面倒だと思います。正当な理由がない限り、Stringを使用する必要があります。

9
Peter Hall