2

考虑以下代码(在操场上):

// calling this function move the ownership of nbr to is_even
// at the end of the function is_even doesn't give the ownership back
fn is_even(nbr: Box<i32>) -> bool {
    *nbr % 2 == 0
}

fn main() {
    let integer = Box::new(42);
    if is_even(integer) {
        print!("is even ");
    }
    println!("{}", integer);
}

我收到以下错误消息:

example.rs:10:17: 10:24 error: use of moved value: `integer` [E0382]
example.rs:10   println!("{}", integer);

example.rs:7:13: 7:20 note: `integer` moved here because it has type `Box<i32>`, which is non-copyable
example.rs:7    if is_even(integer) {

我不明白为什么。好的,当我调用 时is_even,我将所有权授予此函数,但在该函数结束时is_even不再需要所有权。这是一个不可变(只读)的所有权转移,所以我们确定它不会在main保留时被删除integer-> 使用它似乎是安全的。

还是有这个错误。为什么以及解决方法是什么?

4

2 回答 2

6

当我打电话时is_even,我将所有权授予此功能

确切地。您已转让所有权。您不再拥有它,该功能将做它想做的事。在这种情况下,它会释放内存,所以你绝对不能在调用后使用它。

该功能不再需要所有权

这就是它被丢弃的原因。

它是不可变(只读)的所有权转移

那是不存在的。您完全转让所有权,没有半途而废。

所以我们确定它没有被删除

实际上,我们确信它已经被释放了,这是一件非常好的事情。Rust 为我们解决了这个问题,所以你永远不必问“谁应该释放这个?”

那么如何解决呢?这很简单:传递对内部值的引用,而不是整个框。这会借用价值(可变或不可变,由您决定)并且所有权不会转移。

fn is_even(nbr: &i32) -> bool { ... }
于 2015-09-02T12:20:54.023 回答
4

如果您想保留您的盒子的所有权,那么您必须is_even 借用它,而不是拥有它。这是您的代码的工作版本:

// calling this function move the ownership of nbr to is_even
// at the end of the function is_even doesn't give the ownership back
fn is_even(nbr: &Box<i32>) -> bool {
    **nbr % 2 == 0
}

fn main() {
    let integer = Box::new(42);
    if is_even(&integer) {
        print!("is even ");
    }
    println!("{}", integer);
}

请注意,is_even现在需要一个对Box 的引用(使用 a ),当我们调用该函数时&,我们必须传入一个引用(再次使用 a )。&最后,该函数现在对引用而不是值进行操作,因此我们需要添加另一个*以取消引用它,然后才能对其进行操作。

但是,避免使用对拥有其内容的值(例如StringorVecBox)的非可变引用是一个很好的经验法则。该函数可以重写如下:

fn is_even(nbr: &i32) -> bool {
    *nbr % 2 == 0
}

这适用于对整数的任何引用,而不仅仅是Boxes 中的引用。

于 2015-09-02T12:14:33.957 回答