2014-11-15 85 views
1

我有一個小型庫,它導出帶有生命週期註釋的結構體。現在我試圖從另一個程序中使用它,但現在我似乎也需要在那裏使用生命週期註釋。基本上我這樣做:生命週期註釋或&str vs字符串

// in my lib 
struct Foo<'a> { 
    baz: &'a str 
} 

// another program 
struct Bar { 
    foo: Foo 
} 

它說Bar必須定義一個一生Foo

<anon>:6:10: 6:13 error: wrong number of lifetime parameters: expected 1, found 0 [E0107] 
<anon>:6  foo: Foo 
        ^~~ 

這很容易解決:

struct Bar<'a> { 
    foo: Foo<'a> 
} 

但是,這將意味着我現在還必須爲任何使用Bar的事物定義生命週期,等等,對嗎?如果這是真的,除了使用不需要明確生命週期的類型之外,是否有任何方法可以解決這個問題?或者是否會更好地使用像String這樣的擁有類型?

有點背景,我用&str因爲我不得不調用一個需要作爲參數的函數。雖然轉換它們沒有問題,但它實際上是Vec<(&str, &str)>,所以我的想法是首先使用正確的類型來擺脫轉換。我有一種感覺,那是錯誤的決定,但是我知道什麼...... :)

+0

請注意,Rust中存在「廉價」轉換;按照慣例,那些由'as_'開頭的方法名稱表示。例如'String :: as_slice'產生一個'&str',它借用它來自的'String'。 –

回答

4

是的,目前沒有辦法解決明確的生命時間。考慮的方法是Foo需要明確關於哪個生命週期與其關聯,因爲baz字段取決於它,因此,例如,如果您嘗試使Foo的壽命長於編譯器,則編譯器知道要阻止您數據baz指的是,或者你可以讓方法返回「只要baz活着就活着」的引用。如果您然後將Foo嵌入Bar,則現在Bar需要明確的生存期,因爲Foo取決於它。

如果Foo是「擁有」的字符串,這意味着如果一個Foo應該能夠站在自己獨立的任何可能的壽命(例如範圍),那麼它的確應該是一個String。從String轉換到片是非常便宜的,因爲片僅僅是現有數據的視圖。

但是,如果你總是基於其上綁一個範圍現有數據構建Foo(如傳遞給含Foo情況下,功能等串片)和Foo實例沒有按」 t需要超過現有數據的範圍,那麼如果您將其設置爲String,則必須將片轉換爲String(與後者相比相對較昂貴),然後纔將其轉換回片中的片使用點,在這種情況下,你應該把它作爲一個切片。你當然不應該承擔這種性能損失,只是爲了避免輸入明確的生命週期。

你會發現具有明確生命週期的類型很常見,所以雖然起初看起來令人擔憂,但你會習慣它。