2017-02-28 36 views
4

我不完全理解生活時間,但我認爲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... 
+2

你應該使'layout'成爲'String'而不是'&'static str'。 http://stackoverflow.com/questions/24158114/rust-string-versus-str – kennytm

+0

謝謝,這可以幫助我做到這一點。但是,如果我想使用&str.how來做到這一點?防鏽不能直接編輯生命期嗎? –

+0

@彭靈俊你爲什麼要用'&str'? – wimh

回答

5

b的範圍是new功能,所以它的存儲器將在函數返回時被釋放。但是您試圖從該函數返回對b的引用。如果Rust讓你這麼做,唯一可能使用該引用的代碼將在之後使用它,該值無效。借閱檢查器正在保護您免受未定義的行爲

layout設爲&'static str聽起來好像你在簡化操作,但是期望regex.replace_all的動態分配內存是靜態的是不合理的。在不考慮unsafe代碼的情況下,您應該將生命週期中的任何內容都視爲編譯時常量。例如,一個字符串文字。

正如其他人所說,你可能想要layoutString。 A String&str類似,但其擁有底層str。這意味着當您移動String時,底層str隨之移動。 A &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, 
     }; 
    } 
} 

這使問題一層調用堆棧向上,意思是傳遞給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