在Rust中重复使用变量

3

我有以下代码:

let display_value = entry.path().display();
files_and_dirs.push(DiskEntry {
    path: display_value.to_string(),
    is_dir: is_dir(display_value.to_string()),
    name: display_value.to_string()
});

If I write it thus:

let display_value = entry.path().display();
let dir_name = display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: dir_name,
    is_dir: is_dir(dir_name),
    name: dir_name
});

我遇到了以下错误:

由于dir_name的类型为std :: string :: String,它没有实现Copy特征,因此会发生移动

我知道在Rust中,当分配时值会被移动。我想声明一个变量并在第二个代码块中多次使用它。我该怎么做?

最初的回答:

您可以使用引用来避免将值移动到另一个变量中。例如:

let dir_name = String::from("example");
let second_reference = &dir_name;
let third_reference = &dir_name;

要么通过借用的方式传递它们,例如 is_dir(&dir_name)(如果你的函数允许这样做),要么使用 String 的 clone 方法。 - Leśny Rumcajs
将它们通过借用传递给 is_dir 并不是问题。我想在三个地方声明一个变量并使用它,就像第二个代码块中那样。在 Rust 中应该如何正确实现这一点? - shashanka n
这三个地方不能拥有你传递的数据,所以如果path字段声明为String,你可以将你的单个变量传递到那里,但是你必须克隆它/使用to_owned。在那里和任何地方都会拥有所有权。 - Leśny Rumcajs
@shashankan 如果你想在3个地方使用它,那么你需要要么(a)克隆该值两次,要么(b)借用该值两次。 - Peter Hall
2个回答

8

您的DiskEntryis_dir可能是这样定义的:

struct DiskEntry {
    path: String,
    is_dir: bool,
    name: String,
}

fn is_dir(path: String) -> bool {
    // ...
}

每当有一个类型为String的变量时,该变量需要在内存中拥有自己的字符串副本。
正如错误提示所建议的那样,您可以通过克隆来修复它:
let display_value = entry.path().display();
let dir_name = display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: dir_name.clone(),
    is_dir: is_dir(dir_name.clone()),
    name: dir_name
});

但是你应该避免不必要地克隆数据,因为这是低效的。很容易删除的克隆位于is_dir中-很明显,这种方法不需要永久占有其输入。它可以非常轻松地借用它:
fn is_dir(path: &str) -> bool {
    // ...
}

您可以像这样调用它,以便将String作为&str借用:

is_dir(&dir_name),

另一个情况可能更加棘手。为了避免克隆,您需要使 DiskEntry 结构借用字符串。它应该像这样:
struct DiskEntry<'a> {
    path: &'a str,
    is_dir: bool,
    name: &'a str,
}

let display_value = entry.path().display();
let dir_name = display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: &dir_name,
    is_dir: is_dir(&dir_name),
    name: &dir_name
});

然而,这将限制您对 DiskEntry 的使用;特别是,它不能超出 dir_name 变量的生命周期。如果不了解代码的更广泛上下文,很难知道这可能会引起什么其他问题,但它可能会对其他数据结构产生更广泛的影响。
考虑到您似乎刚开始学习Rust,如果您还不熟悉借用和生命周期,最好接受这个额外克隆,直到您更好地理解并可以自己做出判断为止。

另请参阅:


0
我想在第二个代码块中声明一个变量,并多次使用它。我该怎么做?
你不能这样做,因为“在Rust中,赋值时值会被移动”。编译器不会自动复制大多数类型的值,因为不清楚何时可以进行复制,并且这可能会引入程序员希望避免的开销。
如果你想多次使用一个Clone变量的值 - 只需克隆它。
如果你想避免重复,可以通过使用闭包给计算命名。
let display_value = entry.path().display();
let dir_name = || display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: dir_name(),
    is_dir: is_dir(dir_name()),
    name: dir_name()
});

这不允许您多次使用该值 - 每次调用都会产生一个新值。


谢谢!这正是我在寻找的东西。对于任何查看此内容的JS开发人员的注意事项,这似乎与匿名的箭头函数非常相似。 - shashanka n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接