2014-10-17 44 views
5

我有以下的代碼:「借用值不活得足夠長的」使用與切片一個結構時

extern crate debug; 

use std::mem::size_of_val; 

struct A<'a> { 
    a: &'a [i64], 
} 

fn main() { 
    // code 
} 

當我定義與切片&(即&[1, 2, 3])如以下println!

println!("{} - {:?}", size_of_val(&A { a: &[1, 2, 3] }), A { a: &[1, 2, 3] }); 

輸出是

16 - A<'static>{a: &[1i64, 2i64, 3i64]} 

d efining切片而不&

println!("{} - {:?}", size_of_val(&A { a: [1, 2, 3] }), A { a: [1, 2, 3] }); 

給我相同的結果

16 - A<'static>{a: &[1i64, 2i64, 3i64]} 

如果我第一嘗試綁定一個struct A,其a字段與到的切片的引用初始化的實例(即使用&),一個變量x

let x = A { a: &[1, 2, 3] }; // &[1, 2, 3] is a reference to a slice 

,我試圖執行一個類似的println!作爲以前的

println!("{} - {:?}", size_of_val(&x), x); 

我得到

16 - A<'static>{a: &[1i64, 2i64, 3i64]} 

但是,如果我綁定一個實例的A,其a字段被初始化爲片(不是使用的片的引用),一個變量x

let x = A { a: [1, 2, 3] }; 

,我試圖執行一個類似的println!作爲以前的

println!("{} - {:?}", size_of_val(&x), x); 

我得到下面的生成錯誤:

/prpath/main.rs:12:20: 12:29 error: borrowed value does not live long enough 
/prpath/main.rs:12  let x = A { a: [1 ,2, 3] }; 
             ^~~~~~~~~ 
/prpath/main.rs:11:11: 15:2 note: reference must be valid for the block at 11:10... 
/prpath/main.rs:11 fn main() { 
/prpath/main.rs:12  let x = A { a: [1 ,2, 3] }; 
/prpath/main.rs:13 
/prpath/main.rs:14  println!("{} - `{:?}`", size_of_val(&x), x); 
/prpath/main.rs:15 } 
/prpath/main.rs:12:5: 12:31 note: ...but borrowed value is only valid for the statement at 12:4; consider using a `let` binding to increase its lifetime 
/prpath/main.rs:12  let x = A { a: [1 ,2, 3] }; 
         ^~~~~~~~~~~~~~~~~~~~~~~~~~ 
error: aborting due to previous error 

我期待只有A { a: &[1, 2, 3] }定義被允許,因爲A.a應該有&[i64]類型,但顯然, Rust允許我們不包含&符號。

A { a: &[1, 2, 3] }A { a: [1, 2, 3] }有什麼區別?爲什麼我們允許使用A { a: [1, 2, 3] }(在上面的第二個例子中)?

回答

5

首先,您可以使用[T,..n],其中&[T]是預期的,則轉換到切片是隱含的。所以下面的代碼是完全有效的:

let a = [1u, 2, 3]; 
let b: &[uint] = a; 

你的情況是一個純粹的終生問題。你的結構是

struct A<'a> { 
    a: &'a [i64], 
} 

它擁有一個。切片只不過是對第一個元素的引用和元素數量的計數。這就是爲什麼size_of_val()調用A將始終返回16:它是一個切片的大小,指針的一個u64,以及一個u64的元素數量(您似乎在64位計算機上)。

因此在您的代碼中,該結構不擁有數組。您觀察到的行爲差異是由於數組超出範圍時的差異所致。

第一種情況:

let x = A { a: [1, 2, 3] }; 

在這裏定義的數組,切片存儲到這個數組中你的結構。然後,當到達;時,您的數組超出了範圍並被銷燬,因此x中的引用不再有效:它被編譯器禁止。

第二種情況:

let x = A { a: &[1, 2, 3] }; 

更奇特。你的數組存儲在一個匿名變量中。事實上,寫

let foo = &42u; 

相當於寫

let _anonymousvariable = 42u; 
let foo = &_anonymousvariable; 

除了你不能直接到達_anonymousvariable

這正是你一樣,你的代碼就相當於

let _anonymous_array = [1, 2, 3] 
let x = A { a: &_anonymous_array }; 

,因此是完全有效的。

最後一種情況:

當你直接寫在println!()一切。由於前面的情況,我們現在明白爲什麼這個工程:

println!("{} - {:?}", size_of_val(&A { a: &[1, 2, 3] }), A { a: &[1, 2, 3] }); 

但在這種情況下,沒有問題或者:

println!("{} - {:?}", size_of_val(&A { a: [1, 2, 3] }), A { a: [1, 2, 3] }); 

,因爲你的數組只有走出去的範圍達到;時,和在這一點上不存在對它們的引用,所以它們可以被安全地刪除並且編譯器很高興。

相關問題