如何将循环中的变量更新为对循环内创建的值的引用?

Tho*_*hel 4 lifetime rust borrow-checker

我想进入一个循环,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
}
Run Code Online (Sandbox Code Playgroud)

x一些与计算的结果qm,但它是一个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
}
Run Code Online (Sandbox Code Playgroud)

现在代码将无法编译,因为m它的生命周期比n.我尝试通过做一些棘手的事情或克隆事情来使它工作,但这不是正确的方法.在C中,代码可以工作,因为我们不关心n在退出循环时指向什么,因为在循环之后n没有使用.我完全理解这是Rust和C不同的地方,但我很确定在Rust中这样做是一种干净的方式.

认为我的问题非常笼统; 我不要求对一些特设针对特定问题的解决方案.

She*_*ter 9

正如Chris Emerson指出的那样,你所做的是不安全的,也可能不适合在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));
}
Run Code Online (Sandbox Code Playgroud)

  • @Ben 只有当它做了你认为它会做的事情^_^。这定义了一个**新绑定**(这就是“let”的含义),因此“n”的类型发生了变化,并且您永远不会获得新值。看到[这个版本似乎永远不会增加值](http://play.integer32.com/?gist=37936638d30435da3a72749c59d3adbc&version=stable); 这就是为什么它(和你的解决方案)抱怨“n”是一个未使用的变量。有关更多信息,[请参阅另一个问题](http://stackoverflow.com/q/31798737/155423)。 (2认同)

Chr*_*son 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.
Run Code Online (Sandbox Code Playgroud)

同样,它取决于特定的类型/生命周期,但您可能会分配m给具有较长生命周期的变量,但随后您又回到了第一个示例。