2013-05-20 23 views
3

編者按:本代碼示例來自1.0版之前的Rust版本,並且不具有語法上有效的Rust 1.0代碼。此代碼的更新版本會產生不同的錯誤,但答案仍然包含有價值的信息。借用的向量引用的生命期與它所包含的借來的指針之間的關係是什麼?

我嘗試這個代碼在鏽0.6:

fn test<'r>(xs: &'r [&str]) -> &'r str { 
    return xs[0]; 
} 

我認爲這種類型的簽名是指:「測試需要借來指針,具有壽命「R,以借指向字符串的載體,和借來的指針返回一個字符串,也終身「R但是編譯器說:

refs.rs:2:8: 2:12 error: mismatched types: expected `&'r str` but found `&str` (lifetime mismatch) 
refs.rs:2  return xs[0]; 
         ^~~~ 
refs.rs:1:39: 3:1 note: the lifetime &'r as defined on the block at 1:39... 
refs.rs:1 fn test<'r>(xs: &'r [&str]) -> &'r str { 
refs.rs:2  return xs[0]; 
refs.rs:3 } 
refs.rs:1:39: 3:1 note: ...does not necessarily outlive the anonymous lifetime #1 defined on the block at 1:39 
refs.rs:1 fn test<'r>(xs: &'r [&str]) -> &'r str { 
refs.rs:2  return xs[0]; 
refs.rs:3 } 
error: aborting due to previous error 

這似乎暗示了載體內的指針可能不會生活,只要在(只讀)載體本身這可能嗎?

有一些額外的註釋我需要告訴編譯器這是確定?

同樣地,何談資指針的載體?例如

fn test<'r>(xs: &'r [~str]) -> &'r str { 
    return xs[0]; 
} 

同樣,我希望能借用一個指向矢量元素的指針,至少只要借用了整個列表。

對於背景下,我原來的問題試圖與擁有指針列表延長借點的列表:

fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str] 

的計劃是:建立與所有借來的指針的exended列表,使用它,然後釋放擴展列表,然後釋放擁有指針的原始列表,包括所包含的字符串。

回答

4

第二個版本的test,與擁有/唯一的字符串不工作,只是編譯器必須協助轉換的~str&'r str

fn test<'r>(xs: &'r [~str]) -> &'r str { 
    let tmp: &'r str = xs[0]; 
    tmp 
} 

這部作品的原因是xs矢量擁有它包含,因此編譯器知道它們的生命週期至少是向量的生命週期(因爲它在這樣的借用情況下也很小心可變性,所以字符串永遠不能從向量中移除)。唯一的問題是說服編譯器強制xs[0]切片,這很容易由臨時執行。


extend可能看起來像:

fn extend<'r>(xs: ~[&'r str], ys: &'r [~str]) -> ~[&'r str] { 
    let mut xs = xs; 
    for vec::each(ys) |s| { 
     let tmp: &'r str = *s; 
     xs.push(tmp) 
    } 
    xs 
} 

似乎vec::each(ys)作品,但ys.each沒有,這可能是一個bug(現在我們正在調查這我打開#6655) 。

如果要修改就地的載體,其通常的方法是通過一個可變的參考矢量,即

fn extend<'r>(xs: &mut ~[&'r str], ys: &'r [~str]) { 
    for vec::each(ys) |s| { 
     let tmp: &'r str = *s; 
     xs.push(tmp) 
    } 
} 

這被稱爲等extend(&mut vec, additions)


爲了說明:

rusti> let a = &[~"a", ~"b", ~"c"]; 
() 
rusti> test(a) 
"a" 
rusti> extend(~["1", "2", "3"], a) 
~["1", "2", "3", "a", "b", "c"] 
3

我認爲你的意思是:

fn test<'r>(xs: &[&'r str]) ->  &'r str { 
     return xs[0]; 
} 

也就是說,你把借來包含指向終身[R字符串借來的數組指針,並返回這些指針,同壽命的一個。載體本身的壽命是無關緊要的。

那是因爲你正在返回未在該函數的輸入藉藉來的指針你的第二個例子是行不通的原因:數組是借來的,其內容都沒有。

+0

好的,但爲什麼這是一件無效的事情呢?這個向量怎麼能超過它內部的引用? –

+0

@ThomasLeonard在你的情況下,向量包含指向字符串的指針。如果這些不是唯一的指針,那麼這些字符串可以很容易地超過矢量。 –

+0

@RamonSnir我怎麼能表達與此相反的?我想說,生成的指針至少和提供的矢量一樣長(但可能更長)。 –

0

我認爲這是你的意思:

fn get1<'r, T>(xs: &'r [T]) -> &'r T { 
    return &xs[0]; 
} 

fn main() { 
    let a = ~[1, 2, 3]; 
    let b = [1, 2, 3]; 
    let c = @[1, 2, 3]; 
    let ax = get1(a); 
    let bx = get1(b); 
    let cx = get1(c); 
    println(fmt!("%d %d %d", *ax, *bx, *cx)); 
} 
用繩子

具體來說,它可能不太好(作爲字符串始終按引用),但與價值觀的載體 - 它的工作原理正好。

+0

不幸的是,改變簽名(返回指向字符串而不是字符串的指針)對我來說沒有幫助,因爲我試圖構建一個字符串列表,而不是指向字符串的指針列表。我已經添加了一條關於爲什麼我想要這樣做的提示。 –

0

鏽1.19.0的(也可能是由於鏽1.0),則original code works as expected

fn test<'r>(xs: &'r [&str]) -> &'r str { 
    xs[0] 
} 

fn main() {} 

owned string version also works after updating the syntax

fn test<'r>(xs: &'r [String]) -> &'r str { 
    &xs[0] 
} 

fn main() {} 

更好,一輩子我參考意味着你不需要在函數上有任何明確的生存期(fn test(xs: &[&str]) -> &str,fn test(xs: &[String]) -> &str

我有一種感覺,這個問題歸結爲如何編譯計算(合,對,in)生存期的變化,或者更準確地說,它在Rust 1.0之前對於這種情況沒有正確地計算它的值。正如您正確識別的那樣,由於切片包含引用,引用必須比切片更長。因此,可以安全返回字符串切片,使用壽命較短,匹配爲'r

相關問題