2014-10-17 12 views
5

kod aşağıdaki parça vardır:"ödünç değeri yeterince uzun yaşamaz"

extern crate debug; 

use std::mem::size_of_val; 

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

fn main() { 
    // code 
} 

Birlikte bir dilim tanımlarken & (yani &[1, 2, 3]) println! aşağıdaki gibi

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

çıkış

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

D &

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

olmayan bir dilim efining bana aynı sonucu

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

verir ilk a alan bir dilim için bir referans ile başlatılan bir yapı A, bir örneğini bağlamak için deneyin (yani bir değişken x

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

için,) & kullanarak ve ben bir örneğini bağlamak eğer, Ancak

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

olsun

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

öncekilerin benzer bir println! yürütmek deneyin a alankullanarak bir dilim için bir başvuru başlatılan A,) Ben

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

Ben şu yapı hatasıyla olsun öncekilerin benzer bir println! yürütmek deneyin ve değişken x

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

için:

/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 

bekliyordum A.a&[i64]10 türüne sahip olması gerektiği için yalnızca A { a: &[1, 2, 3] } tanımlamasına izin verildi, ancak, görünüşe göre, Pas, & sembolünü içermemize izin verir.

A { a: &[1, 2, 3] } ve A { a: [1, 2, 3] } arasındaki fark nedir? Neden A { a: [1, 2, 3] }'u kullanalım (yukarıdaki ikinci örnekte)?

cevap

5

İlk olarak, &[T]'un beklendiği bir [T,..n] kodunu kullanabilirsiniz; bu, bir dilim için dönüşüme örtülüdür. Bu nedenle aşağıdaki kod geçerlidir:

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

Durumunuz tamamen yaşam boyu bir problemdir. Sizin yapı bir dilim tutan

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

olduğunu.Bir dilim, birinci öğeye yapılan referanstan ve öğe sayısının bir sayısından başka bir şey değildir. Bu nedenle, A üzerinde size_of_val() çağrılır, her zaman 16 döndürür: bir dilim boyutu, imleç için bir u64 ve öğe sayısı için bir u64 (64 bit bilgisayarda göründüğü gibi).

Kodunuzda yapısında dizinin sahibi yok. Gözlemlediğiniz davranıştaki fark, dizinin kapsam dışı olduğu zamandaki farktan kaynaklanır.

İlk vaka: Burada

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

bir dizi tanımlamak ve yapı içinde bu diziye bir dilim saklar. Ardından, ; numaralı telefona ulaştığınızda, dizininiz kapsam dışıdır ve yok edilir ve dolayısıyla x'daki başvuru artık geçerli değildir: derleyici tarafından yasaklanmıştır.

İkinci durum:

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

Daha tuhaf. Diziniz anonim değişkende saklanır. Aslında,

let foo = &42u; 

yazma doğrudan _anonymousvariable ulaşamaz Bunun dışında

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

yazmaya eşdeğerdir. Tam olarak sizin için aynı olduğunu

, kodunuz

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

eşdeğerdir ve bu nedenle mükemmel geçerlidir.

Son durum:

Eğer println!() doğrudan şeyi yazın.

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

ancak bu durumda hiçbir sorun vardır: Bir önceki durumda sayesinde, artık bu işleri neden görmek ; ulaşan yaparken diziler sadece kapsam dışına çıkar, çünkü

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

ve Bu noktadan sonra hiçbir referans yoktur, bu yüzden güvenle silinebilir ve derleyici mutlu olur.

İlgili konular