在Rust中重用变量

时间:2019-05-26 09:36:18

标签: rust move-semantics

我有以下代码:

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()
});

如果我这样写:

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中,赋值时会四处移动。我想声明一个变量,并在第二个代码块中多次使用它。我该怎么做?

2 个答案:

答案 0 :(得分:4)

您的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,如果您对借阅和终生还不满意,最简单的方法就是接受这个额外的克隆,直到您有更好的理解并自己做出判断为止。 / p>


另请参阅:

答案 1 :(得分: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()
});

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