DÜZENLEME: Sadece yazdığınızı fark ettim: "Kutu, Kopya vb. Geçici bir çözüm olduğunun farkındayım ama çoğunlukla ilgileniyorum deyimsiz pas çözümü ", ama ben bütün cevabı zaten yazdım. : P Ve 'un altındaki çözümler, deyimsel Rust'tur, bu, hafızanın işleyiş şeklidir! C veya C++'da stack-allocated verilere işaretçiler döndürmeye çalışmayın çünkü derleyici sizi durdurmasa bile, bu iyi bir şey gelmeyecektir anlamına gelmez. ;)
bir referans dönüş her zaman, bu referans şart işleve bir parametre olmuştur. Eğer verilere başvurular dönen eğer Başka bir deyişle, bütün bu verilerin fonksiyonunun dışında tahsis edilmiş olmalıdır. Bunu anlıyor gibisin, sadece açık olduğundan emin olmak istiyorum. :) Kullanım durumunuz ne bağlı bu sorunu çözme birçok potansiyel yolu vardır
bulunmaktadır. Bu özel örnekte
, sen, sadece hiç referanslarla rahatsız etmeden foo
sahiplik verebilir sonra herhangi bir şey için x
gerekmediğinden:
fn foo(x: i64) -> Vec<i64> {
std::iter::repeat(x * 2).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(x));
}
Ama İstemediğiniz diyelim sahipliğini foo
'a geçirmek için. Sen hala sürece temel değeri mutasyona istemiyordu olarak referansların bir vektör geri dönebilirler:
fn foo(x: &i64) -> Vec<&i64> {
std::iter::repeat(x).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(&x));
}
... ve aynı şekilde sizin sürece istemediğini olarak temel değeri mutasyona olabilir Yeni işaretçileri dağıtmak için:
... ama elbette ikisini de yapmak istiyorsunuz. Yani eğer hafıza ayırıyorsanız ve geri vermek istiyorsanız, onu yığından başka bir yerde yapmanız gerekir. Box
kullanarak sadece yığın üzerinde şeyler yapabileceğim bir şey,:
// Just for illustration, see the next example for a better approach
fn foo(x: &i64) -> Vec<Box<i64>> {
std::iter::repeat(Box::new(x * 2)).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(&x));
}
... Yukarıda ile Sadece yığını kullanarak genel bir araç olarak Box
farkındayız emin olmak olsa .Gerçekten, basitçe bir Vec
kullanarak veri yığınının üzerine yerleştirilmiş olacağı anlamına gelir, bu nedenle bu işleri:
fn foo(x: &i64) -> Vec<i64> {
std::iter::repeat(x * 2).take(5).collect()
}
fn main() {
let x = 5;
println!("{:?}", foo(&x));
}
yukarıdaki gibi hiç bir kullanım durumu farklı bir şey talep edebilecek olsa burada muhtemelen en deyimsel örneğidir.
Alternatif olarak, C'nin kitabından, bir hileyi çekebilirdi ve foo
ait dışında hafızayı önceden tahsis ve sonra buna bir referans geçmesi:
fn foo(x: &i64, v: &mut [i64; 5]) {
for i in v {
*i = x * 2;
}
}
fn main() {
let x = 5;
let mut v = [0; 5]; // fixed-size array on the stack
foo(&x, &mut v);
println!("{:?}", v);
}
Son olarak fonksiyonu zorunluluk eğerve parametrelerini referans olarak almak için, referans verisini ve mutasyona tabi tutmalısınız, referansın kendisini kopyalamanız gerekir ve bu kopyalanmış referansları geri göndermelisiniz, daha sonrakullanabilirsiniz Bunun için:
use std::cell::Cell;
fn foo(x: &Cell<i64>) -> Vec<&Cell<i64>> {
x.set(x.get() * 2);
std::iter::repeat(x).take(5).collect()
}
fn main() {
let x = Cell::new(5);
println!("{:?}", foo(&x));
}
Cell
, verimli ve non-şaşırtıcı hem nota rağmen sadece (bütün temel sayısal türleri yapmak) Copy
özelliği uygulamak türlerinde Cell
çalışır. Yazıcınız Copy
'u uygulamıyorsa, RefCell
ile aynı şeyi yapabilirsiniz, ancak hafif bir çalışma süresi yükü yükler ve "borçlanmayı" yanlış alırsanız çalışma zamanında panik olasılığını açar.
* ama bence aynı sorunların üstesinden gelebilir * - bunu denediniz mi? Neden aynı sorunlara sahip olacağını düşünüyorsun? – Shepmaster
@Shepmaster I64'leri yeni işlevde, yığınta ayırırsam, kızarırdım. Ama öyle görünüyor ki çalışıyor. Sanırım bunun sebebi arayanı tekrar arayan kişiye verdiğim için, borç kontrolörü üzülmüyor, yani borç yok mu? Bu tür bir çözüm, Kutu veya Hücre gibi bir yığın-ayrılmış yapıyı kullanmaktan daha idiomatik midir? – William
Borcunuz olmadığı konusunda haklısınız: 'i64'leri yığına ayırın, daha sonra bunları' Vec'e aktarın ve daha sonra 'Vec'in mülkiyetini tekrar arayan kişiye aktarın. * içeren bir yığın-ayrılmış yapısını kullanarak daha idiomatik * - bir 'Vec' ** **" bir yığın-ayrılmış yapıya sahip "dir. Bu durumda bir 'Vec ''' Box' veya 'Cell' kullanmaktan daha aptalca olduğunu söyleyebilirim. Bu özel örnekte, bir dizi de döndürebilirsiniz '[i64; 5] 'bildiğinizden, kaç tane geri dönüş yapacağınızı biliyorsunuz. – Shepmaster