借用新对象实例时如何指定生命周期?
How to specify a lifetime when borrowing a new object instance?
我想用 fill
函数范围内的 Foo
实例填充 Vec<Foo>
。这甚至可能生锈吗?我尝试过生命周期,但我无法将我从 tutorials/documentation/samples 中学到的东西投射到这个特定的用例上。
pub struct Foo {
pub integer: Box<u32>,
}
pub fn fill1(mut vec: Vec<&Foo>) {
// Error: argument requires that borrow lasts for `'1`
vec.push(&Foo { integer: Box::new(1) });
}
pub fn fill2<'a>(mut vec: Vec<&'a Foo>) {
// Error: argument requires that borrow lasts for `'a`
vec.push(&Foo { integer: Box::new(1) });
}
如果这没有意义(我很乐意理解为什么),我正在考虑修改 pub fn fill3(mut vec: Vec<Foo>, foos: Foos)
的方法签名(不借用)。但是,如果我这样做,我还有很多其他问题。
这行不通,因为您正在推送对局部变量的引用,这些引用将在方法完成时被销毁。如果您像这样重写方法,可以更容易地看到这一点:
pub fn fill1(mut vec: Vec<&Foo>) {
// a local variable - exists only within the stack frame of the method
let foo = Foo { integer: Box::new(1) };
// `&foo` will be a dangling reference after the method exits
vec.push(&foo);
} // foo is destroyed here, but `vec` still exists, containing pointers to freed memory, or memory used by some other function
But in this case, why would this work? fn fill(mut vec: Vec<Foo>, foos: Foos)
它将某种工作,但在该方法结束时,您的整个向量将被删除(解除分配),所以这个版本的fill()
不正确任何一个。相反,您应该接受对可变向量的引用,这意味着其他人拥有该向量,但它为您提供了修改它的临时访问权限:
// vec is a mutable reference, thus the vector's
// life is not tied with the function execution
// i.e. it will still exist after the function executes
pub fn fill_ok(vec: &mut Vec<Foo>) {
let foo = Foo {
integer: Box::new(1),
};
// `foo` is copied to the vector, which is
// backed by a heap allocation. The local
// variable `foo` will still be destroyed,
// but the copy in the heap (the vec) will
// remain
vec.push(foo);
}
My usecase is indeed a little more complex. Passing a reference to a mutable vector fixes the first part of the problem, but then things are still tricky to me if I want to be able to add both objects owned from the outside and from the function scope
在这种情况下,您可以按照@Peter Hall 的建议使用Cow
。它必须有变体 - 一个包含引用,一个包含拥有的值。
缺点是您的对象必须实现 Clone
特性。如果这不是一个选项,您可以轻松推出自己的 Cow
而无需该要求
#[derive(Clone)] // Objects must implement `Clone` in order to be used with `Cow`
pub struct Foo {
pub integer: Box<u32>,
}
pub fn fill2<'a>(vec: &'a mut Vec<Cow<'a, Foo>>, foos: &'a Foos) {
vec.push(Cow::Owned(Foo {
integer: Box::new(1),
}));
for foo in &foos.foos {
vec.push(Cow::Borrowed(foo));
}
}
我想用 fill
函数范围内的 Foo
实例填充 Vec<Foo>
。这甚至可能生锈吗?我尝试过生命周期,但我无法将我从 tutorials/documentation/samples 中学到的东西投射到这个特定的用例上。
pub struct Foo {
pub integer: Box<u32>,
}
pub fn fill1(mut vec: Vec<&Foo>) {
// Error: argument requires that borrow lasts for `'1`
vec.push(&Foo { integer: Box::new(1) });
}
pub fn fill2<'a>(mut vec: Vec<&'a Foo>) {
// Error: argument requires that borrow lasts for `'a`
vec.push(&Foo { integer: Box::new(1) });
}
如果这没有意义(我很乐意理解为什么),我正在考虑修改 pub fn fill3(mut vec: Vec<Foo>, foos: Foos)
的方法签名(不借用)。但是,如果我这样做,我还有很多其他问题。
这行不通,因为您正在推送对局部变量的引用,这些引用将在方法完成时被销毁。如果您像这样重写方法,可以更容易地看到这一点:
pub fn fill1(mut vec: Vec<&Foo>) {
// a local variable - exists only within the stack frame of the method
let foo = Foo { integer: Box::new(1) };
// `&foo` will be a dangling reference after the method exits
vec.push(&foo);
} // foo is destroyed here, but `vec` still exists, containing pointers to freed memory, or memory used by some other function
But in this case, why would this work?
fn fill(mut vec: Vec<Foo>, foos: Foos)
它将某种工作,但在该方法结束时,您的整个向量将被删除(解除分配),所以这个版本的fill()
不正确任何一个。相反,您应该接受对可变向量的引用,这意味着其他人拥有该向量,但它为您提供了修改它的临时访问权限:
// vec is a mutable reference, thus the vector's
// life is not tied with the function execution
// i.e. it will still exist after the function executes
pub fn fill_ok(vec: &mut Vec<Foo>) {
let foo = Foo {
integer: Box::new(1),
};
// `foo` is copied to the vector, which is
// backed by a heap allocation. The local
// variable `foo` will still be destroyed,
// but the copy in the heap (the vec) will
// remain
vec.push(foo);
}
My usecase is indeed a little more complex. Passing a reference to a mutable vector fixes the first part of the problem, but then things are still tricky to me if I want to be able to add both objects owned from the outside and from the function scope
在这种情况下,您可以按照@Peter Hall 的建议使用Cow
。它必须有变体 - 一个包含引用,一个包含拥有的值。
缺点是您的对象必须实现 Clone
特性。如果这不是一个选项,您可以轻松推出自己的 Cow
而无需该要求
#[derive(Clone)] // Objects must implement `Clone` in order to be used with `Cow`
pub struct Foo {
pub integer: Box<u32>,
}
pub fn fill2<'a>(vec: &'a mut Vec<Cow<'a, Foo>>, foos: &'a Foos) {
vec.push(Cow::Owned(Foo {
integer: Box::new(1),
}));
for foo in &foos.foos {
vec.push(Cow::Borrowed(foo));
}
}