我想输入一个带有变量n
的循环,该循环由函数借用。在每一步中,n
都会获得一个新值;退出循环时,在其他变量的帮助下完成作业,n
永远不会再次使用。
如果我不使用推荐信,我会这样:
fn test(n: Thing) -> usize {
// stuff
let mut n = n;
for i in 1..10 {
let (q, m) = n.do_something(...);
n = m;
// stuff with x
}
x
}
x
是使用q
和m
进行某些计算的结果,但它是usize
类型,我在这部分中没有遇到任何问题代码。我没有测试这段代码,但这是个主意。我可以编写像这样的代码。
因为我想用引用来做;我试着写:
fn test(n: &Thing) -> usize {
// stuff
let mut n = n;
for i in 1..10 {
let (q, m) = (*n).do_something(...);
n = &m;
// stuff with x
}
x
}
现在代码无法编译,因为m
的生命周期比n
短。我尝试通过做一些棘手的事情或克隆事情来使它工作,但这不是正确的方法。在C中,代码可以工作,因为我们不关心退出循环时n
指向的内容,因为在循环之后n
没有被使用。我完全理解这是Rust和C不同的地方,但我很确定在Rust中这样做是一种干净的方式。
认为我的问题非常笼统;我不是要求针对特定问题的某些 ad-hoc 解决方案。
答案 0 :(得分:9)
作为Chris Emerson points out,您正在做的是不安全,也可能不适合在C中编写类似的代码。在每次循环迭代结束时,您引用的变量超出范围,因此在下一次迭代开始时您将有一个悬空指针。这将导致Rust试图阻止的所有内存错误; Rust阻止你做一些你认为安全的坏事。
如果你想要借用或拥有的东西;这是一个Cow
:
use std::borrow::Cow;
#[derive(Clone)]
struct Thing;
impl Thing {
fn do_something(&self) -> (usize, Thing) {
(1, Thing)
}
}
fn test(n: &Thing) -> usize {
let mut n = Cow::Borrowed(n);
let mut x = 0;
for _ in 1..10 {
let (q, m) = n.do_something();
n = Cow::Owned(m);
x = x + q;
}
x
}
fn main() {
println!("{}", test(&Thing));
}
答案 1 :(得分:4)
如果我理解这一点,问题与循环之外的生活无关; m
的活动时间不足以保留下一次迭代的参考。
let mut n = n;
for i in 1..10 {
let (q,m) = (*n).do_something(...)
n = &m
} // At this point m is no longer live, i.e. doesn't live until the next iteration.
同样,它取决于特定的类型/生命周期,但您可以将m
分配给具有更长生命周期的变量,但之后您将回到第一个示例。